/*!
 * Phidget22 JavaScript Library (Network Client) v3.26.1 (https://phidgets.com)
 *  phidget22 release 1.26.20260821
 * Copyright 2017-2026 Phidgets Inc.
 * Licensed under ISC
 */
(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
    typeof define === 'function' && define.amd ? define(['exports'], factory) :
    (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.phidget22 = {}));
})(this, (function (exports) { 'use strict';

    /**
     * Generates SHA-256 hash of string.
     *
     * @param   {string} msg - String to be hashed
     * @returns {string} Hash of msg as hex character string
     */
    function sha256hash(msg) {
      /**
       * Rotates right (circular right shift) value x by n positions [3.2.4].
       * @private
       */
      function ROTR(n, x) {
        return x >>> n | x << 32 - n;
      }
      /**
       * Logical functions [4.1.2].
       * @private
       */
      function S0(x) {
        return ROTR(2, x) ^ ROTR(13, x) ^ ROTR(22, x);
      }
      function S1(x) {
        return ROTR(6, x) ^ ROTR(11, x) ^ ROTR(25, x);
      }
      function s0(x) {
        return ROTR(7, x) ^ ROTR(18, x) ^ x >>> 3;
      }
      function s1(x) {
        return ROTR(17, x) ^ ROTR(19, x) ^ x >>> 10;
      }
      function Ch(x, y, z) {
        return x & y ^ ~x & z;
      }
      function Maj(x, y, z) {
        return x & y ^ x & z ^ y & z;
      }
      /**
       * Hexadecimal representation of a number.
       * @private
       */
      function toHexStr(n) {
        let s = "",
          v;
        for (let i = 7; i >= 0; i--) {
          v = n >>> i * 4 & 0xf;
          s += v.toString(16);
        }
        return s;
      }
      msg = unescape(encodeURIComponent(msg));
      const K = [0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2];
      const H = [0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19];
      msg += String.fromCharCode(0x80);
      const l = msg.length / 4 + 2;
      const N = Math.ceil(l / 16);
      const M = new Array(N);
      for (let i = 0; i < N; i++) {
        M[i] = new Array(16);
        for (let j = 0; j < 16; j++) {
          M[i][j] = msg.charCodeAt(i * 64 + j * 4) << 24 | msg.charCodeAt(i * 64 + j * 4 + 1) << 16 | msg.charCodeAt(i * 64 + j * 4 + 2) << 8 | msg.charCodeAt(i * 64 + j * 4 + 3);
        }
      }
      M[N - 1][14] = (msg.length - 1) * 8 / Math.pow(2, 32);
      M[N - 1][14] = Math.floor(M[N - 1][14]);
      M[N - 1][15] = (msg.length - 1) * 8 & 0xffffffff;
      const W = new Array(64);
      let a, b, c, d, e, f, g, h;
      for (let i = 0; i < N; i++) {
        for (let t = 0; t < 16; t++) W[t] = M[i][t];
        for (let t = 16; t < 64; t++) W[t] = s1(W[t - 2]) + W[t - 7] + s0(W[t - 15]) + W[t - 16] & 0xffffffff;
        a = H[0];
        b = H[1];
        c = H[2];
        d = H[3];
        e = H[4];
        f = H[5];
        g = H[6];
        h = H[7];
        for (let t = 0; t < 64; t++) {
          const T1 = h + S1(e) + Ch(e, f, g) + K[t] + W[t];
          const T2 = S0(a) + Maj(a, b, c);
          h = g;
          g = f;
          f = e;
          e = d + T1 & 0xffffffff;
          d = c;
          c = b;
          b = a;
          a = T1 + T2 & 0xffffffff;
        }
        H[0] = H[0] + a & 0xffffffff;
        H[1] = H[1] + b & 0xffffffff;
        H[2] = H[2] + c & 0xffffffff;
        H[3] = H[3] + d & 0xffffffff;
        H[4] = H[4] + e & 0xffffffff;
        H[5] = H[5] + f & 0xffffffff;
        H[6] = H[6] + g & 0xffffffff;
        H[7] = H[7] + h & 0xffffffff;
      }
      return toHexStr(H[0]) + toHexStr(H[1]) + toHexStr(H[2]) + toHexStr(H[3]) + toHexStr(H[4]) + toHexStr(H[5]) + toHexStr(H[6]) + toHexStr(H[7]);
    }

    var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};

    function getDefaultExportFromCjs (x) {
    	return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
    }

    var es_object_keys = {};

    var globalThis_1;
    var hasRequiredGlobalThis;
    function requireGlobalThis () {
    	if (hasRequiredGlobalThis) return globalThis_1;
    	hasRequiredGlobalThis = 1;
    	var check = function (it) {
    	  return it && it.Math === Math && it;
    	};
    	globalThis_1 =
    	  check(typeof globalThis == 'object' && globalThis) ||
    	  check(typeof window == 'object' && window) ||
    	  check(typeof self == 'object' && self) ||
    	  check(typeof commonjsGlobal == 'object' && commonjsGlobal) ||
    	  check(typeof globalThis_1 == 'object' && globalThis_1) ||
    	  (function () { return this; })() || Function('return this')();
    	return globalThis_1;
    }

    var fails;
    var hasRequiredFails;
    function requireFails () {
    	if (hasRequiredFails) return fails;
    	hasRequiredFails = 1;
    	fails = function (exec) {
    	  try {
    	    return !!exec();
    	  } catch (error) {
    	    return true;
    	  }
    	};
    	return fails;
    }

    var functionBindNative;
    var hasRequiredFunctionBindNative;
    function requireFunctionBindNative () {
    	if (hasRequiredFunctionBindNative) return functionBindNative;
    	hasRequiredFunctionBindNative = 1;
    	var fails =  requireFails();
    	functionBindNative = !fails(function () {
    	  var test = function () {  }.bind();
    	  return typeof test != 'function' || test.hasOwnProperty('prototype');
    	});
    	return functionBindNative;
    }

    var functionApply;
    var hasRequiredFunctionApply;
    function requireFunctionApply () {
    	if (hasRequiredFunctionApply) return functionApply;
    	hasRequiredFunctionApply = 1;
    	var NATIVE_BIND =  requireFunctionBindNative();
    	var FunctionPrototype = Function.prototype;
    	var apply = FunctionPrototype.apply;
    	var call = FunctionPrototype.call;
    	functionApply = typeof Reflect == 'object' && Reflect.apply || (NATIVE_BIND ? call.bind(apply) : function () {
    	  return call.apply(apply, arguments);
    	});
    	return functionApply;
    }

    var functionUncurryThis;
    var hasRequiredFunctionUncurryThis;
    function requireFunctionUncurryThis () {
    	if (hasRequiredFunctionUncurryThis) return functionUncurryThis;
    	hasRequiredFunctionUncurryThis = 1;
    	var NATIVE_BIND =  requireFunctionBindNative();
    	var FunctionPrototype = Function.prototype;
    	var call = FunctionPrototype.call;
    	var uncurryThisWithBind = NATIVE_BIND && FunctionPrototype.bind.bind(call, call);
    	functionUncurryThis = NATIVE_BIND ? uncurryThisWithBind : function (fn) {
    	  return function () {
    	    return call.apply(fn, arguments);
    	  };
    	};
    	return functionUncurryThis;
    }

    var classofRaw;
    var hasRequiredClassofRaw;
    function requireClassofRaw () {
    	if (hasRequiredClassofRaw) return classofRaw;
    	hasRequiredClassofRaw = 1;
    	var uncurryThis =  requireFunctionUncurryThis();
    	var toString = uncurryThis({}.toString);
    	var stringSlice = uncurryThis(''.slice);
    	classofRaw = function (it) {
    	  return stringSlice(toString(it), 8, -1);
    	};
    	return classofRaw;
    }

    var functionUncurryThisClause;
    var hasRequiredFunctionUncurryThisClause;
    function requireFunctionUncurryThisClause () {
    	if (hasRequiredFunctionUncurryThisClause) return functionUncurryThisClause;
    	hasRequiredFunctionUncurryThisClause = 1;
    	var classofRaw =  requireClassofRaw();
    	var uncurryThis =  requireFunctionUncurryThis();
    	functionUncurryThisClause = function (fn) {
    	  if (classofRaw(fn) === 'Function') return uncurryThis(fn);
    	};
    	return functionUncurryThisClause;
    }

    var isCallable;
    var hasRequiredIsCallable;
    function requireIsCallable () {
    	if (hasRequiredIsCallable) return isCallable;
    	hasRequiredIsCallable = 1;
    	var documentAll = typeof document == 'object' && document.all;
    	isCallable = typeof documentAll == 'undefined' && documentAll !== undefined ? function (argument) {
    	  return typeof argument == 'function' || argument === documentAll;
    	} : function (argument) {
    	  return typeof argument == 'function';
    	};
    	return isCallable;
    }

    var objectGetOwnPropertyDescriptor = {};

    var descriptors;
    var hasRequiredDescriptors;
    function requireDescriptors () {
    	if (hasRequiredDescriptors) return descriptors;
    	hasRequiredDescriptors = 1;
    	var fails =  requireFails();
    	descriptors = !fails(function () {
    	  return Object.defineProperty({}, 1, { get: function () { return 7; } })[1] !== 7;
    	});
    	return descriptors;
    }

    var functionCall;
    var hasRequiredFunctionCall;
    function requireFunctionCall () {
    	if (hasRequiredFunctionCall) return functionCall;
    	hasRequiredFunctionCall = 1;
    	var NATIVE_BIND =  requireFunctionBindNative();
    	var call = Function.prototype.call;
    	functionCall = NATIVE_BIND ? call.bind(call) : function () {
    	  return call.apply(call, arguments);
    	};
    	return functionCall;
    }

    var objectPropertyIsEnumerable = {};

    var hasRequiredObjectPropertyIsEnumerable;
    function requireObjectPropertyIsEnumerable () {
    	if (hasRequiredObjectPropertyIsEnumerable) return objectPropertyIsEnumerable;
    	hasRequiredObjectPropertyIsEnumerable = 1;
    	var $propertyIsEnumerable = {}.propertyIsEnumerable;
    	var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
    	var NASHORN_BUG = getOwnPropertyDescriptor && !$propertyIsEnumerable.call({ 1: 2 }, 1);
    	objectPropertyIsEnumerable.f = NASHORN_BUG ? function propertyIsEnumerable(V) {
    	  var descriptor = getOwnPropertyDescriptor(this, V);
    	  return !!descriptor && descriptor.enumerable;
    	} : $propertyIsEnumerable;
    	return objectPropertyIsEnumerable;
    }

    var createPropertyDescriptor;
    var hasRequiredCreatePropertyDescriptor;
    function requireCreatePropertyDescriptor () {
    	if (hasRequiredCreatePropertyDescriptor) return createPropertyDescriptor;
    	hasRequiredCreatePropertyDescriptor = 1;
    	createPropertyDescriptor = function (bitmap, value) {
    	  return {
    	    enumerable: !(bitmap & 1),
    	    configurable: !(bitmap & 2),
    	    writable: !(bitmap & 4),
    	    value: value
    	  };
    	};
    	return createPropertyDescriptor;
    }

    var indexedObject;
    var hasRequiredIndexedObject;
    function requireIndexedObject () {
    	if (hasRequiredIndexedObject) return indexedObject;
    	hasRequiredIndexedObject = 1;
    	var uncurryThis =  requireFunctionUncurryThis();
    	var fails =  requireFails();
    	var classof =  requireClassofRaw();
    	var $Object = Object;
    	var split = uncurryThis(''.split);
    	indexedObject = fails(function () {
    	  return !$Object('z').propertyIsEnumerable(0);
    	}) ? function (it) {
    	  return classof(it) === 'String' ? split(it, '') : $Object(it);
    	} : $Object;
    	return indexedObject;
    }

    var isNullOrUndefined;
    var hasRequiredIsNullOrUndefined;
    function requireIsNullOrUndefined () {
    	if (hasRequiredIsNullOrUndefined) return isNullOrUndefined;
    	hasRequiredIsNullOrUndefined = 1;
    	isNullOrUndefined = function (it) {
    	  return it === null || it === undefined;
    	};
    	return isNullOrUndefined;
    }

    var requireObjectCoercible;
    var hasRequiredRequireObjectCoercible;
    function requireRequireObjectCoercible () {
    	if (hasRequiredRequireObjectCoercible) return requireObjectCoercible;
    	hasRequiredRequireObjectCoercible = 1;
    	var isNullOrUndefined =  requireIsNullOrUndefined();
    	var $TypeError = TypeError;
    	requireObjectCoercible = function (it) {
    	  if (isNullOrUndefined(it)) throw new $TypeError("Can't call method on " + it);
    	  return it;
    	};
    	return requireObjectCoercible;
    }

    var toIndexedObject;
    var hasRequiredToIndexedObject;
    function requireToIndexedObject () {
    	if (hasRequiredToIndexedObject) return toIndexedObject;
    	hasRequiredToIndexedObject = 1;
    	var IndexedObject =  requireIndexedObject();
    	var requireObjectCoercible =  requireRequireObjectCoercible();
    	toIndexedObject = function (it) {
    	  return IndexedObject(requireObjectCoercible(it));
    	};
    	return toIndexedObject;
    }

    var isObject;
    var hasRequiredIsObject;
    function requireIsObject () {
    	if (hasRequiredIsObject) return isObject;
    	hasRequiredIsObject = 1;
    	var isCallable =  requireIsCallable();
    	isObject = function (it) {
    	  return typeof it == 'object' ? it !== null : isCallable(it);
    	};
    	return isObject;
    }

    var path;
    var hasRequiredPath;
    function requirePath () {
    	if (hasRequiredPath) return path;
    	hasRequiredPath = 1;
    	path = {};
    	return path;
    }

    var getBuiltIn;
    var hasRequiredGetBuiltIn;
    function requireGetBuiltIn () {
    	if (hasRequiredGetBuiltIn) return getBuiltIn;
    	hasRequiredGetBuiltIn = 1;
    	var path =  requirePath();
    	var globalThis =  requireGlobalThis();
    	var isCallable =  requireIsCallable();
    	var aFunction = function (variable) {
    	  return isCallable(variable) ? variable : undefined;
    	};
    	getBuiltIn = function (namespace, method) {
    	  return arguments.length < 2 ? aFunction(path[namespace]) || aFunction(globalThis[namespace])
    	    : path[namespace] && path[namespace][method] || globalThis[namespace] && globalThis[namespace][method];
    	};
    	return getBuiltIn;
    }

    var objectIsPrototypeOf;
    var hasRequiredObjectIsPrototypeOf;
    function requireObjectIsPrototypeOf () {
    	if (hasRequiredObjectIsPrototypeOf) return objectIsPrototypeOf;
    	hasRequiredObjectIsPrototypeOf = 1;
    	var uncurryThis =  requireFunctionUncurryThis();
    	objectIsPrototypeOf = uncurryThis({}.isPrototypeOf);
    	return objectIsPrototypeOf;
    }

    var environmentUserAgent;
    var hasRequiredEnvironmentUserAgent;
    function requireEnvironmentUserAgent () {
    	if (hasRequiredEnvironmentUserAgent) return environmentUserAgent;
    	hasRequiredEnvironmentUserAgent = 1;
    	var globalThis =  requireGlobalThis();
    	var navigator = globalThis.navigator;
    	var userAgent = navigator && navigator.userAgent;
    	environmentUserAgent = userAgent ? String(userAgent) : '';
    	return environmentUserAgent;
    }

    var environmentV8Version;
    var hasRequiredEnvironmentV8Version;
    function requireEnvironmentV8Version () {
    	if (hasRequiredEnvironmentV8Version) return environmentV8Version;
    	hasRequiredEnvironmentV8Version = 1;
    	var globalThis =  requireGlobalThis();
    	var userAgent =  requireEnvironmentUserAgent();
    	var process = globalThis.process;
    	var Deno = globalThis.Deno;
    	var versions = process && process.versions || Deno && Deno.version;
    	var v8 = versions && versions.v8;
    	var match, version;
    	if (v8) {
    	  match = v8.split('.');
    	  version = match[0] > 0 && match[0] < 4 ? 1 : +(match[0] + match[1]);
    	}
    	if (!version && userAgent) {
    	  match = userAgent.match(/Edge\/(\d+)/);
    	  if (!match || match[1] >= 74) {
    	    match = userAgent.match(/Chrome\/(\d+)/);
    	    if (match) version = +match[1];
    	  }
    	}
    	environmentV8Version = version;
    	return environmentV8Version;
    }

    var symbolConstructorDetection;
    var hasRequiredSymbolConstructorDetection;
    function requireSymbolConstructorDetection () {
    	if (hasRequiredSymbolConstructorDetection) return symbolConstructorDetection;
    	hasRequiredSymbolConstructorDetection = 1;
    	var V8_VERSION =  requireEnvironmentV8Version();
    	var fails =  requireFails();
    	var globalThis =  requireGlobalThis();
    	var $String = globalThis.String;
    	symbolConstructorDetection = !!Object.getOwnPropertySymbols && !fails(function () {
    	  var symbol = Symbol('symbol detection');
    	  return !$String(symbol) || !(Object(symbol) instanceof Symbol) ||
    	    !Symbol.sham && V8_VERSION && V8_VERSION < 41;
    	});
    	return symbolConstructorDetection;
    }

    var useSymbolAsUid;
    var hasRequiredUseSymbolAsUid;
    function requireUseSymbolAsUid () {
    	if (hasRequiredUseSymbolAsUid) return useSymbolAsUid;
    	hasRequiredUseSymbolAsUid = 1;
    	var NATIVE_SYMBOL =  requireSymbolConstructorDetection();
    	useSymbolAsUid = NATIVE_SYMBOL &&
    	  !Symbol.sham &&
    	  typeof Symbol.iterator == 'symbol';
    	return useSymbolAsUid;
    }

    var isSymbol;
    var hasRequiredIsSymbol;
    function requireIsSymbol () {
    	if (hasRequiredIsSymbol) return isSymbol;
    	hasRequiredIsSymbol = 1;
    	var getBuiltIn =  requireGetBuiltIn();
    	var isCallable =  requireIsCallable();
    	var isPrototypeOf =  requireObjectIsPrototypeOf();
    	var USE_SYMBOL_AS_UID =  requireUseSymbolAsUid();
    	var $Object = Object;
    	isSymbol = USE_SYMBOL_AS_UID ? function (it) {
    	  return typeof it == 'symbol';
    	} : function (it) {
    	  var $Symbol = getBuiltIn('Symbol');
    	  return isCallable($Symbol) && isPrototypeOf($Symbol.prototype, $Object(it));
    	};
    	return isSymbol;
    }

    var tryToString;
    var hasRequiredTryToString;
    function requireTryToString () {
    	if (hasRequiredTryToString) return tryToString;
    	hasRequiredTryToString = 1;
    	var $String = String;
    	tryToString = function (argument) {
    	  try {
    	    return $String(argument);
    	  } catch (error) {
    	    return 'Object';
    	  }
    	};
    	return tryToString;
    }

    var aCallable;
    var hasRequiredACallable;
    function requireACallable () {
    	if (hasRequiredACallable) return aCallable;
    	hasRequiredACallable = 1;
    	var isCallable =  requireIsCallable();
    	var tryToString =  requireTryToString();
    	var $TypeError = TypeError;
    	aCallable = function (argument) {
    	  if (isCallable(argument)) return argument;
    	  throw new $TypeError(tryToString(argument) + ' is not a function');
    	};
    	return aCallable;
    }

    var getMethod;
    var hasRequiredGetMethod;
    function requireGetMethod () {
    	if (hasRequiredGetMethod) return getMethod;
    	hasRequiredGetMethod = 1;
    	var aCallable =  requireACallable();
    	var isNullOrUndefined =  requireIsNullOrUndefined();
    	getMethod = function (V, P) {
    	  var func = V[P];
    	  return isNullOrUndefined(func) ? undefined : aCallable(func);
    	};
    	return getMethod;
    }

    var ordinaryToPrimitive;
    var hasRequiredOrdinaryToPrimitive;
    function requireOrdinaryToPrimitive () {
    	if (hasRequiredOrdinaryToPrimitive) return ordinaryToPrimitive;
    	hasRequiredOrdinaryToPrimitive = 1;
    	var call =  requireFunctionCall();
    	var isCallable =  requireIsCallable();
    	var isObject =  requireIsObject();
    	var $TypeError = TypeError;
    	ordinaryToPrimitive = function (input, pref) {
    	  var fn, val;
    	  if (pref === 'string' && isCallable(fn = input.toString) && !isObject(val = call(fn, input))) return val;
    	  if (isCallable(fn = input.valueOf) && !isObject(val = call(fn, input))) return val;
    	  if (pref !== 'string' && isCallable(fn = input.toString) && !isObject(val = call(fn, input))) return val;
    	  throw new $TypeError("Can't convert object to primitive value");
    	};
    	return ordinaryToPrimitive;
    }

    var sharedStore = {exports: {}};

    var isPure;
    var hasRequiredIsPure;
    function requireIsPure () {
    	if (hasRequiredIsPure) return isPure;
    	hasRequiredIsPure = 1;
    	isPure = true;
    	return isPure;
    }

    var defineGlobalProperty;
    var hasRequiredDefineGlobalProperty;
    function requireDefineGlobalProperty () {
    	if (hasRequiredDefineGlobalProperty) return defineGlobalProperty;
    	hasRequiredDefineGlobalProperty = 1;
    	var globalThis =  requireGlobalThis();
    	var defineProperty = Object.defineProperty;
    	defineGlobalProperty = function (key, value) {
    	  try {
    	    defineProperty(globalThis, key, { value: value, configurable: true, writable: true });
    	  } catch (error) {
    	    globalThis[key] = value;
    	  } return value;
    	};
    	return defineGlobalProperty;
    }

    var hasRequiredSharedStore;
    function requireSharedStore () {
    	if (hasRequiredSharedStore) return sharedStore.exports;
    	hasRequiredSharedStore = 1;
    	var IS_PURE =  requireIsPure();
    	var globalThis =  requireGlobalThis();
    	var defineGlobalProperty =  requireDefineGlobalProperty();
    	var SHARED = '__core-js_shared__';
    	var store = sharedStore.exports = globalThis[SHARED] || defineGlobalProperty(SHARED, {});
    	(store.versions || (store.versions = [])).push({
    	  version: '3.49.0',
    	  mode: IS_PURE ? 'pure' : 'global',
    	  copyright: '© 2013–2025 Denis Pushkarev (zloirock.ru), 2025–2026 CoreJS Company (core-js.io). All rights reserved.',
    	  license: 'https://github.com/zloirock/core-js/blob/v3.49.0/LICENSE',
    	  source: 'https://github.com/zloirock/core-js'
    	});
    	return sharedStore.exports;
    }

    var shared;
    var hasRequiredShared;
    function requireShared () {
    	if (hasRequiredShared) return shared;
    	hasRequiredShared = 1;
    	var store =  requireSharedStore();
    	shared = function (key, value) {
    	  return store[key] || (store[key] = value || {});
    	};
    	return shared;
    }

    var toObject;
    var hasRequiredToObject;
    function requireToObject () {
    	if (hasRequiredToObject) return toObject;
    	hasRequiredToObject = 1;
    	var requireObjectCoercible =  requireRequireObjectCoercible();
    	var $Object = Object;
    	toObject = function (argument) {
    	  return $Object(requireObjectCoercible(argument));
    	};
    	return toObject;
    }

    var hasOwnProperty_1;
    var hasRequiredHasOwnProperty;
    function requireHasOwnProperty () {
    	if (hasRequiredHasOwnProperty) return hasOwnProperty_1;
    	hasRequiredHasOwnProperty = 1;
    	var uncurryThis =  requireFunctionUncurryThis();
    	var toObject =  requireToObject();
    	var hasOwnProperty = uncurryThis({}.hasOwnProperty);
    	hasOwnProperty_1 = Object.hasOwn || function hasOwn(it, key) {
    	  return hasOwnProperty(toObject(it), key);
    	};
    	return hasOwnProperty_1;
    }

    var uid;
    var hasRequiredUid;
    function requireUid () {
    	if (hasRequiredUid) return uid;
    	hasRequiredUid = 1;
    	var uncurryThis =  requireFunctionUncurryThis();
    	var id = 0;
    	var postfix = Math.random();
    	var toString = uncurryThis(1.1.toString);
    	uid = function (key) {
    	  return 'Symbol(' + (key === undefined ? '' : key) + ')_' + toString(++id + postfix, 36);
    	};
    	return uid;
    }

    var wellKnownSymbol;
    var hasRequiredWellKnownSymbol;
    function requireWellKnownSymbol () {
    	if (hasRequiredWellKnownSymbol) return wellKnownSymbol;
    	hasRequiredWellKnownSymbol = 1;
    	var globalThis =  requireGlobalThis();
    	var shared =  requireShared();
    	var hasOwn =  requireHasOwnProperty();
    	var uid =  requireUid();
    	var NATIVE_SYMBOL =  requireSymbolConstructorDetection();
    	var USE_SYMBOL_AS_UID =  requireUseSymbolAsUid();
    	var Symbol = globalThis.Symbol;
    	var WellKnownSymbolsStore = shared('wks');
    	var createWellKnownSymbol = USE_SYMBOL_AS_UID ? Symbol['for'] || Symbol : Symbol && Symbol.withoutSetter || uid;
    	wellKnownSymbol = function (name) {
    	  if (!hasOwn(WellKnownSymbolsStore, name)) {
    	    WellKnownSymbolsStore[name] = NATIVE_SYMBOL && hasOwn(Symbol, name)
    	      ? Symbol[name]
    	      : createWellKnownSymbol('Symbol.' + name);
    	  } return WellKnownSymbolsStore[name];
    	};
    	return wellKnownSymbol;
    }

    var toPrimitive;
    var hasRequiredToPrimitive;
    function requireToPrimitive () {
    	if (hasRequiredToPrimitive) return toPrimitive;
    	hasRequiredToPrimitive = 1;
    	var call =  requireFunctionCall();
    	var isObject =  requireIsObject();
    	var isSymbol =  requireIsSymbol();
    	var getMethod =  requireGetMethod();
    	var ordinaryToPrimitive =  requireOrdinaryToPrimitive();
    	var wellKnownSymbol =  requireWellKnownSymbol();
    	var $TypeError = TypeError;
    	var TO_PRIMITIVE = wellKnownSymbol('toPrimitive');
    	toPrimitive = function (input, pref) {
    	  if (!isObject(input) || isSymbol(input)) return input;
    	  var exoticToPrim = getMethod(input, TO_PRIMITIVE);
    	  var result;
    	  if (exoticToPrim) {
    	    if (pref === undefined) pref = 'default';
    	    result = call(exoticToPrim, input, pref);
    	    if (!isObject(result) || isSymbol(result)) return result;
    	    throw new $TypeError("Can't convert object to primitive value");
    	  }
    	  if (pref === undefined) pref = 'number';
    	  return ordinaryToPrimitive(input, pref);
    	};
    	return toPrimitive;
    }

    var toPropertyKey;
    var hasRequiredToPropertyKey;
    function requireToPropertyKey () {
    	if (hasRequiredToPropertyKey) return toPropertyKey;
    	hasRequiredToPropertyKey = 1;
    	var toPrimitive =  requireToPrimitive();
    	var isSymbol =  requireIsSymbol();
    	toPropertyKey = function (argument) {
    	  var key = toPrimitive(argument, 'string');
    	  return isSymbol(key) ? key : key + '';
    	};
    	return toPropertyKey;
    }

    var documentCreateElement;
    var hasRequiredDocumentCreateElement;
    function requireDocumentCreateElement () {
    	if (hasRequiredDocumentCreateElement) return documentCreateElement;
    	hasRequiredDocumentCreateElement = 1;
    	var globalThis =  requireGlobalThis();
    	var isObject =  requireIsObject();
    	var document = globalThis.document;
    	var EXISTS = isObject(document) && isObject(document.createElement);
    	documentCreateElement = function (it) {
    	  return EXISTS ? document.createElement(it) : {};
    	};
    	return documentCreateElement;
    }

    var ie8DomDefine;
    var hasRequiredIe8DomDefine;
    function requireIe8DomDefine () {
    	if (hasRequiredIe8DomDefine) return ie8DomDefine;
    	hasRequiredIe8DomDefine = 1;
    	var DESCRIPTORS =  requireDescriptors();
    	var fails =  requireFails();
    	var createElement =  requireDocumentCreateElement();
    	ie8DomDefine = !DESCRIPTORS && !fails(function () {
    	  return Object.defineProperty(createElement('div'), 'a', {
    	    get: function () { return 7; }
    	  }).a !== 7;
    	});
    	return ie8DomDefine;
    }

    var hasRequiredObjectGetOwnPropertyDescriptor;
    function requireObjectGetOwnPropertyDescriptor () {
    	if (hasRequiredObjectGetOwnPropertyDescriptor) return objectGetOwnPropertyDescriptor;
    	hasRequiredObjectGetOwnPropertyDescriptor = 1;
    	var DESCRIPTORS =  requireDescriptors();
    	var call =  requireFunctionCall();
    	var propertyIsEnumerableModule =  requireObjectPropertyIsEnumerable();
    	var createPropertyDescriptor =  requireCreatePropertyDescriptor();
    	var toIndexedObject =  requireToIndexedObject();
    	var toPropertyKey =  requireToPropertyKey();
    	var hasOwn =  requireHasOwnProperty();
    	var IE8_DOM_DEFINE =  requireIe8DomDefine();
    	var $getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
    	objectGetOwnPropertyDescriptor.f = DESCRIPTORS ? $getOwnPropertyDescriptor : function getOwnPropertyDescriptor(O, P) {
    	  O = toIndexedObject(O);
    	  P = toPropertyKey(P);
    	  if (IE8_DOM_DEFINE) try {
    	    return $getOwnPropertyDescriptor(O, P);
    	  } catch (error) {  }
    	  if (hasOwn(O, P)) return createPropertyDescriptor(!call(propertyIsEnumerableModule.f, O, P), O[P]);
    	};
    	return objectGetOwnPropertyDescriptor;
    }

    var isForced_1;
    var hasRequiredIsForced;
    function requireIsForced () {
    	if (hasRequiredIsForced) return isForced_1;
    	hasRequiredIsForced = 1;
    	var fails =  requireFails();
    	var isCallable =  requireIsCallable();
    	var replacement = /#|\.prototype\./;
    	var isForced = function (feature, detection) {
    	  var value = data[normalize(feature)];
    	  return value === POLYFILL ? true
    	    : value === NATIVE ? false
    	    : isCallable(detection) ? fails(detection)
    	    : !!detection;
    	};
    	var normalize = isForced.normalize = function (string) {
    	  return String(string).replace(replacement, '.').toLowerCase();
    	};
    	var data = isForced.data = {};
    	var NATIVE = isForced.NATIVE = 'N';
    	var POLYFILL = isForced.POLYFILL = 'P';
    	isForced_1 = isForced;
    	return isForced_1;
    }

    var functionBindContext;
    var hasRequiredFunctionBindContext;
    function requireFunctionBindContext () {
    	if (hasRequiredFunctionBindContext) return functionBindContext;
    	hasRequiredFunctionBindContext = 1;
    	var uncurryThis =  requireFunctionUncurryThisClause();
    	var aCallable =  requireACallable();
    	var NATIVE_BIND =  requireFunctionBindNative();
    	var bind = uncurryThis(uncurryThis.bind);
    	functionBindContext = function (fn, that) {
    	  aCallable(fn);
    	  return that === undefined ? fn : NATIVE_BIND ? bind(fn, that) : function () {
    	    return fn.apply(that, arguments);
    	  };
    	};
    	return functionBindContext;
    }

    var objectDefineProperty = {};

    var v8PrototypeDefineBug;
    var hasRequiredV8PrototypeDefineBug;
    function requireV8PrototypeDefineBug () {
    	if (hasRequiredV8PrototypeDefineBug) return v8PrototypeDefineBug;
    	hasRequiredV8PrototypeDefineBug = 1;
    	var DESCRIPTORS =  requireDescriptors();
    	var fails =  requireFails();
    	v8PrototypeDefineBug = DESCRIPTORS && fails(function () {
    	  return Object.defineProperty(function () {  }, 'prototype', {
    	    value: 42,
    	    writable: false
    	  }).prototype !== 42;
    	});
    	return v8PrototypeDefineBug;
    }

    var anObject;
    var hasRequiredAnObject;
    function requireAnObject () {
    	if (hasRequiredAnObject) return anObject;
    	hasRequiredAnObject = 1;
    	var isObject =  requireIsObject();
    	var $String = String;
    	var $TypeError = TypeError;
    	anObject = function (argument) {
    	  if (isObject(argument)) return argument;
    	  throw new $TypeError($String(argument) + ' is not an object');
    	};
    	return anObject;
    }

    var hasRequiredObjectDefineProperty;
    function requireObjectDefineProperty () {
    	if (hasRequiredObjectDefineProperty) return objectDefineProperty;
    	hasRequiredObjectDefineProperty = 1;
    	var DESCRIPTORS =  requireDescriptors();
    	var IE8_DOM_DEFINE =  requireIe8DomDefine();
    	var V8_PROTOTYPE_DEFINE_BUG =  requireV8PrototypeDefineBug();
    	var anObject =  requireAnObject();
    	var toPropertyKey =  requireToPropertyKey();
    	var $TypeError = TypeError;
    	var $defineProperty = Object.defineProperty;
    	var $getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
    	var ENUMERABLE = 'enumerable';
    	var CONFIGURABLE = 'configurable';
    	var WRITABLE = 'writable';
    	objectDefineProperty.f = DESCRIPTORS ? V8_PROTOTYPE_DEFINE_BUG ? function defineProperty(O, P, Attributes) {
    	  anObject(O);
    	  P = toPropertyKey(P);
    	  anObject(Attributes);
    	  if (typeof O === 'function' && P === 'prototype' && 'value' in Attributes && WRITABLE in Attributes && !Attributes[WRITABLE]) {
    	    var current = $getOwnPropertyDescriptor(O, P);
    	    if (current && current[WRITABLE]) {
    	      O[P] = Attributes.value;
    	      Attributes = {
    	        configurable: CONFIGURABLE in Attributes ? Attributes[CONFIGURABLE] : current[CONFIGURABLE],
    	        enumerable: ENUMERABLE in Attributes ? Attributes[ENUMERABLE] : current[ENUMERABLE],
    	        writable: false
    	      };
    	    }
    	  } return $defineProperty(O, P, Attributes);
    	} : $defineProperty : function defineProperty(O, P, Attributes) {
    	  anObject(O);
    	  P = toPropertyKey(P);
    	  anObject(Attributes);
    	  if (IE8_DOM_DEFINE) try {
    	    return $defineProperty(O, P, Attributes);
    	  } catch (error) {  }
    	  if ('get' in Attributes || 'set' in Attributes) throw new $TypeError('Accessors not supported');
    	  if ('value' in Attributes) O[P] = Attributes.value;
    	  return O;
    	};
    	return objectDefineProperty;
    }

    var createNonEnumerableProperty;
    var hasRequiredCreateNonEnumerableProperty;
    function requireCreateNonEnumerableProperty () {
    	if (hasRequiredCreateNonEnumerableProperty) return createNonEnumerableProperty;
    	hasRequiredCreateNonEnumerableProperty = 1;
    	var DESCRIPTORS =  requireDescriptors();
    	var definePropertyModule =  requireObjectDefineProperty();
    	var createPropertyDescriptor =  requireCreatePropertyDescriptor();
    	createNonEnumerableProperty = DESCRIPTORS ? function (object, key, value) {
    	  return definePropertyModule.f(object, key, createPropertyDescriptor(1, value));
    	} : function (object, key, value) {
    	  object[key] = value;
    	  return object;
    	};
    	return createNonEnumerableProperty;
    }

    var _export;
    var hasRequired_export;
    function require_export () {
    	if (hasRequired_export) return _export;
    	hasRequired_export = 1;
    	var globalThis =  requireGlobalThis();
    	var apply =  requireFunctionApply();
    	var uncurryThis =  requireFunctionUncurryThisClause();
    	var isCallable =  requireIsCallable();
    	var getOwnPropertyDescriptor =  requireObjectGetOwnPropertyDescriptor().f;
    	var isForced =  requireIsForced();
    	var path =  requirePath();
    	var bind =  requireFunctionBindContext();
    	var createNonEnumerableProperty =  requireCreateNonEnumerableProperty();
    	var hasOwn =  requireHasOwnProperty();
    	 requireSharedStore();
    	var wrapConstructor = function (NativeConstructor) {
    	  var Wrapper = function (a, b, c) {
    	    if (this instanceof Wrapper) {
    	      switch (arguments.length) {
    	        case 0: return new NativeConstructor();
    	        case 1: return new NativeConstructor(a);
    	        case 2: return new NativeConstructor(a, b);
    	      } return new NativeConstructor(a, b, c);
    	    } return apply(NativeConstructor, this, arguments);
    	  };
    	  Wrapper.prototype = NativeConstructor.prototype;
    	  return Wrapper;
    	};
    	_export = function (options, source) {
    	  var TARGET = options.target;
    	  var GLOBAL = options.global;
    	  var STATIC = options.stat;
    	  var PROTO = options.proto;
    	  var nativeSource = GLOBAL ? globalThis : STATIC ? globalThis[TARGET] : globalThis[TARGET] && globalThis[TARGET].prototype;
    	  var target = GLOBAL ? path : path[TARGET] || createNonEnumerableProperty(path, TARGET, {})[TARGET];
    	  var targetPrototype = target.prototype;
    	  var FORCED, USE_NATIVE, VIRTUAL_PROTOTYPE;
    	  var key, sourceProperty, targetProperty, nativeProperty, resultProperty, descriptor;
    	  for (key in source) {
    	    FORCED = isForced(GLOBAL ? key : TARGET + (STATIC ? '.' : '#') + key, options.forced);
    	    USE_NATIVE = !FORCED && nativeSource && hasOwn(nativeSource, key);
    	    targetProperty = target[key];
    	    if (USE_NATIVE) if (options.dontCallGetSet) {
    	      descriptor = getOwnPropertyDescriptor(nativeSource, key);
    	      nativeProperty = descriptor && descriptor.value;
    	    } else nativeProperty = nativeSource[key];
    	    sourceProperty = (USE_NATIVE && nativeProperty) ? nativeProperty : source[key];
    	    if (!FORCED && !PROTO && typeof targetProperty == typeof sourceProperty) continue;
    	    if (options.bind && USE_NATIVE) resultProperty = bind(sourceProperty, globalThis);
    	    else if (options.wrap && USE_NATIVE) resultProperty = wrapConstructor(sourceProperty);
    	    else if (PROTO && isCallable(sourceProperty)) resultProperty = uncurryThis(sourceProperty);
    	    else resultProperty = sourceProperty;
    	    if (options.sham || (sourceProperty && sourceProperty.sham) || (targetProperty && targetProperty.sham)) {
    	      createNonEnumerableProperty(resultProperty, 'sham', true);
    	    }
    	    createNonEnumerableProperty(target, key, resultProperty);
    	    if (PROTO) {
    	      VIRTUAL_PROTOTYPE = TARGET + 'Prototype';
    	      if (!hasOwn(path, VIRTUAL_PROTOTYPE)) {
    	        createNonEnumerableProperty(path, VIRTUAL_PROTOTYPE, {});
    	      }
    	      createNonEnumerableProperty(path[VIRTUAL_PROTOTYPE], key, sourceProperty);
    	      if (options.real && targetPrototype && (FORCED || !targetPrototype[key])) {
    	        createNonEnumerableProperty(targetPrototype, key, sourceProperty);
    	      }
    	    }
    	  }
    	};
    	return _export;
    }

    var mathTrunc;
    var hasRequiredMathTrunc;
    function requireMathTrunc () {
    	if (hasRequiredMathTrunc) return mathTrunc;
    	hasRequiredMathTrunc = 1;
    	var ceil = Math.ceil;
    	var floor = Math.floor;
    	mathTrunc = Math.trunc || function trunc(x) {
    	  var n = +x;
    	  return (n > 0 ? floor : ceil)(n);
    	};
    	return mathTrunc;
    }

    var toIntegerOrInfinity;
    var hasRequiredToIntegerOrInfinity;
    function requireToIntegerOrInfinity () {
    	if (hasRequiredToIntegerOrInfinity) return toIntegerOrInfinity;
    	hasRequiredToIntegerOrInfinity = 1;
    	var trunc =  requireMathTrunc();
    	toIntegerOrInfinity = function (argument) {
    	  var number = +argument;
    	  return number !== number || number === 0 ? 0 : trunc(number);
    	};
    	return toIntegerOrInfinity;
    }

    var toAbsoluteIndex;
    var hasRequiredToAbsoluteIndex;
    function requireToAbsoluteIndex () {
    	if (hasRequiredToAbsoluteIndex) return toAbsoluteIndex;
    	hasRequiredToAbsoluteIndex = 1;
    	var toIntegerOrInfinity =  requireToIntegerOrInfinity();
    	var max = Math.max;
    	var min = Math.min;
    	toAbsoluteIndex = function (index, length) {
    	  var integer = toIntegerOrInfinity(index);
    	  return integer < 0 ? max(integer + length, 0) : min(integer, length);
    	};
    	return toAbsoluteIndex;
    }

    var toLength;
    var hasRequiredToLength;
    function requireToLength () {
    	if (hasRequiredToLength) return toLength;
    	hasRequiredToLength = 1;
    	var toIntegerOrInfinity =  requireToIntegerOrInfinity();
    	var min = Math.min;
    	toLength = function (argument) {
    	  var len = toIntegerOrInfinity(argument);
    	  return len > 0 ? min(len, 0x1FFFFFFFFFFFFF) : 0;
    	};
    	return toLength;
    }

    var lengthOfArrayLike;
    var hasRequiredLengthOfArrayLike;
    function requireLengthOfArrayLike () {
    	if (hasRequiredLengthOfArrayLike) return lengthOfArrayLike;
    	hasRequiredLengthOfArrayLike = 1;
    	var toLength =  requireToLength();
    	lengthOfArrayLike = function (obj) {
    	  return toLength(obj.length);
    	};
    	return lengthOfArrayLike;
    }

    var arrayIncludes;
    var hasRequiredArrayIncludes;
    function requireArrayIncludes () {
    	if (hasRequiredArrayIncludes) return arrayIncludes;
    	hasRequiredArrayIncludes = 1;
    	var toIndexedObject =  requireToIndexedObject();
    	var toAbsoluteIndex =  requireToAbsoluteIndex();
    	var lengthOfArrayLike =  requireLengthOfArrayLike();
    	var createMethod = function (IS_INCLUDES) {
    	  return function ($this, el, fromIndex) {
    	    var O = toIndexedObject($this);
    	    var length = lengthOfArrayLike(O);
    	    if (length === 0) return !IS_INCLUDES && -1;
    	    var index = toAbsoluteIndex(fromIndex, length);
    	    var value;
    	    if (IS_INCLUDES && el !== el) while (length > index) {
    	      value = O[index++];
    	      if (value !== value) return true;
    	    } else for (;length > index; index++) {
    	      if ((IS_INCLUDES || index in O) && O[index] === el) return IS_INCLUDES || index || 0;
    	    } return !IS_INCLUDES && -1;
    	  };
    	};
    	arrayIncludes = {
    	  includes: createMethod(true),
    	  indexOf: createMethod(false)
    	};
    	return arrayIncludes;
    }

    var hiddenKeys;
    var hasRequiredHiddenKeys;
    function requireHiddenKeys () {
    	if (hasRequiredHiddenKeys) return hiddenKeys;
    	hasRequiredHiddenKeys = 1;
    	hiddenKeys = {};
    	return hiddenKeys;
    }

    var objectKeysInternal;
    var hasRequiredObjectKeysInternal;
    function requireObjectKeysInternal () {
    	if (hasRequiredObjectKeysInternal) return objectKeysInternal;
    	hasRequiredObjectKeysInternal = 1;
    	var uncurryThis =  requireFunctionUncurryThis();
    	var hasOwn =  requireHasOwnProperty();
    	var toIndexedObject =  requireToIndexedObject();
    	var indexOf =  requireArrayIncludes().indexOf;
    	var hiddenKeys =  requireHiddenKeys();
    	var push = uncurryThis([].push);
    	objectKeysInternal = function (object, names) {
    	  var O = toIndexedObject(object);
    	  var i = 0;
    	  var result = [];
    	  var key;
    	  for (key in O) !hasOwn(hiddenKeys, key) && hasOwn(O, key) && push(result, key);
    	  while (names.length > i) if (hasOwn(O, key = names[i++])) {
    	    ~indexOf(result, key) || push(result, key);
    	  }
    	  return result;
    	};
    	return objectKeysInternal;
    }

    var enumBugKeys;
    var hasRequiredEnumBugKeys;
    function requireEnumBugKeys () {
    	if (hasRequiredEnumBugKeys) return enumBugKeys;
    	hasRequiredEnumBugKeys = 1;
    	enumBugKeys = [
    	  'constructor',
    	  'hasOwnProperty',
    	  'isPrototypeOf',
    	  'propertyIsEnumerable',
    	  'toLocaleString',
    	  'toString',
    	  'valueOf'
    	];
    	return enumBugKeys;
    }

    var objectKeys;
    var hasRequiredObjectKeys;
    function requireObjectKeys () {
    	if (hasRequiredObjectKeys) return objectKeys;
    	hasRequiredObjectKeys = 1;
    	var internalObjectKeys =  requireObjectKeysInternal();
    	var enumBugKeys =  requireEnumBugKeys();
    	objectKeys = Object.keys || function keys(O) {
    	  return internalObjectKeys(O, enumBugKeys);
    	};
    	return objectKeys;
    }

    var hasRequiredEs_object_keys;
    function requireEs_object_keys () {
    	if (hasRequiredEs_object_keys) return es_object_keys;
    	hasRequiredEs_object_keys = 1;
    	var $ =  require_export();
    	var toObject =  requireToObject();
    	var nativeKeys =  requireObjectKeys();
    	var fails =  requireFails();
    	var FAILS_ON_PRIMITIVES = fails(function () { nativeKeys(1); });
    	$({ target: 'Object', stat: true, forced: FAILS_ON_PRIMITIVES }, {
    	  keys: function keys(it) {
    	    return nativeKeys(toObject(it));
    	  }
    	});
    	return es_object_keys;
    }

    var es_json_parse = {};

    var isArray;
    var hasRequiredIsArray;
    function requireIsArray () {
    	if (hasRequiredIsArray) return isArray;
    	hasRequiredIsArray = 1;
    	var classof =  requireClassofRaw();
    	isArray = Array.isArray || function isArray(argument) {
    	  return classof(argument) === 'Array';
    	};
    	return isArray;
    }

    var toStringTagSupport;
    var hasRequiredToStringTagSupport;
    function requireToStringTagSupport () {
    	if (hasRequiredToStringTagSupport) return toStringTagSupport;
    	hasRequiredToStringTagSupport = 1;
    	var wellKnownSymbol =  requireWellKnownSymbol();
    	var TO_STRING_TAG = wellKnownSymbol('toStringTag');
    	var test = {};
    	test[TO_STRING_TAG] = 'z';
    	toStringTagSupport = String(test) === '[object z]';
    	return toStringTagSupport;
    }

    var classof;
    var hasRequiredClassof;
    function requireClassof () {
    	if (hasRequiredClassof) return classof;
    	hasRequiredClassof = 1;
    	var TO_STRING_TAG_SUPPORT =  requireToStringTagSupport();
    	var isCallable =  requireIsCallable();
    	var classofRaw =  requireClassofRaw();
    	var wellKnownSymbol =  requireWellKnownSymbol();
    	var TO_STRING_TAG = wellKnownSymbol('toStringTag');
    	var $Object = Object;
    	var CORRECT_ARGUMENTS = classofRaw(function () { return arguments; }()) === 'Arguments';
    	var tryGet = function (it, key) {
    	  try {
    	    return it[key];
    	  } catch (error) {  }
    	};
    	classof = TO_STRING_TAG_SUPPORT ? classofRaw : function (it) {
    	  var O, tag, result;
    	  return it === undefined ? 'Undefined' : it === null ? 'Null'
    	    : typeof (tag = tryGet(O = $Object(it), TO_STRING_TAG)) == 'string' ? tag
    	    : CORRECT_ARGUMENTS ? classofRaw(O)
    	    : (result = classofRaw(O)) === 'Object' && isCallable(O.callee) ? 'Arguments' : result;
    	};
    	return classof;
    }

    var toString;
    var hasRequiredToString;
    function requireToString () {
    	if (hasRequiredToString) return toString;
    	hasRequiredToString = 1;
    	var classof =  requireClassof();
    	var $String = String;
    	toString = function (argument) {
    	  if (classof(argument) === 'Symbol') throw new TypeError('Cannot convert a Symbol value to a string');
    	  return $String(argument);
    	};
    	return toString;
    }

    var createProperty;
    var hasRequiredCreateProperty;
    function requireCreateProperty () {
    	if (hasRequiredCreateProperty) return createProperty;
    	hasRequiredCreateProperty = 1;
    	var DESCRIPTORS =  requireDescriptors();
    	var definePropertyModule =  requireObjectDefineProperty();
    	var createPropertyDescriptor =  requireCreatePropertyDescriptor();
    	createProperty = function (object, key, value) {
    	  if (DESCRIPTORS) definePropertyModule.f(object, key, createPropertyDescriptor(0, value));
    	  else object[key] = value;
    	};
    	return createProperty;
    }

    var parseJsonString;
    var hasRequiredParseJsonString;
    function requireParseJsonString () {
    	if (hasRequiredParseJsonString) return parseJsonString;
    	hasRequiredParseJsonString = 1;
    	var uncurryThis =  requireFunctionUncurryThis();
    	var hasOwn =  requireHasOwnProperty();
    	var $SyntaxError = SyntaxError;
    	var $parseInt = parseInt;
    	var fromCharCode = String.fromCharCode;
    	var at = uncurryThis(''.charAt);
    	var slice = uncurryThis(''.slice);
    	var exec = uncurryThis(/./.exec);
    	var codePoints = {
    	  '\\"': '"',
    	  '\\\\': '\\',
    	  '\\/': '/',
    	  '\\b': '\b',
    	  '\\f': '\f',
    	  '\\n': '\n',
    	  '\\r': '\r',
    	  '\\t': '\t'
    	};
    	var IS_4_HEX_DIGITS = /^[\da-f]{4}$/i;
    	var IS_C0_CONTROL_CODE = /^[\u0000-\u001F]$/;
    	parseJsonString = function (source, i) {
    	  var unterminated = true;
    	  var value = '';
    	  while (i < source.length) {
    	    var chr = at(source, i);
    	    if (chr === '\\') {
    	      var twoChars = slice(source, i, i + 2);
    	      if (hasOwn(codePoints, twoChars)) {
    	        value += codePoints[twoChars];
    	        i += 2;
    	      } else if (twoChars === '\\u') {
    	        i += 2;
    	        var fourHexDigits = slice(source, i, i + 4);
    	        if (!exec(IS_4_HEX_DIGITS, fourHexDigits)) throw new $SyntaxError('Bad Unicode escape at: ' + i);
    	        value += fromCharCode($parseInt(fourHexDigits, 16));
    	        i += 4;
    	      } else throw new $SyntaxError('Unknown escape sequence: "' + twoChars + '"');
    	    } else if (chr === '"') {
    	      unterminated = false;
    	      i++;
    	      break;
    	    } else {
    	      if (exec(IS_C0_CONTROL_CODE, chr)) throw new $SyntaxError('Bad control character in string literal at: ' + i);
    	      value += chr;
    	      i++;
    	    }
    	  }
    	  if (unterminated) throw new $SyntaxError('Unterminated string at: ' + i);
    	  return { value: value, end: i };
    	};
    	return parseJsonString;
    }

    var hasRequiredEs_json_parse;
    function requireEs_json_parse () {
    	if (hasRequiredEs_json_parse) return es_json_parse;
    	hasRequiredEs_json_parse = 1;
    	var $ =  require_export();
    	var DESCRIPTORS =  requireDescriptors();
    	var globalThis =  requireGlobalThis();
    	var getBuiltIn =  requireGetBuiltIn();
    	var uncurryThis =  requireFunctionUncurryThis();
    	var call =  requireFunctionCall();
    	var isCallable =  requireIsCallable();
    	var isObject =  requireIsObject();
    	var isArray =  requireIsArray();
    	var hasOwn =  requireHasOwnProperty();
    	var toString =  requireToString();
    	var lengthOfArrayLike =  requireLengthOfArrayLike();
    	var createProperty =  requireCreateProperty();
    	var fails =  requireFails();
    	var parseJSONString =  requireParseJsonString();
    	var NATIVE_SYMBOL =  requireSymbolConstructorDetection();
    	var JSON = globalThis.JSON;
    	var Number = globalThis.Number;
    	var SyntaxError = globalThis.SyntaxError;
    	var nativeParse = JSON && JSON.parse;
    	var enumerableOwnProperties = getBuiltIn('Object', 'keys');
    	var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
    	var at = uncurryThis(''.charAt);
    	var slice = uncurryThis(''.slice);
    	var exec = uncurryThis(/./.exec);
    	var push = uncurryThis([].push);
    	var IS_DIGIT = /^\d$/;
    	var IS_NON_ZERO_DIGIT = /^[1-9]$/;
    	var IS_NUMBER_START = /^[\d-]$/;
    	var IS_WHITESPACE = /^[\t\n\r ]$/;
    	var PRIMITIVE = 0;
    	var OBJECT = 1;
    	var $parse = function (source, reviver) {
    	  source = toString(source);
    	  var context = new Context(source, 0);
    	  var root = context.parse();
    	  var value = root.value;
    	  var endIndex = context.skip(IS_WHITESPACE, root.end);
    	  if (endIndex < source.length) {
    	    throw new SyntaxError('Unexpected extra character: "' + at(source, endIndex) + '" after the parsed data at: ' + endIndex);
    	  }
    	  return isCallable(reviver) ? internalize({ '': value }, '', reviver, root) : value;
    	};
    	var internalize = function (holder, name, reviver, node) {
    	  var val = holder[name];
    	  var unmodified = node && val === node.value;
    	  var context = unmodified && typeof node.source == 'string' ? { source: node.source } : {};
    	  var elementRecordsLen, keys, len, i, P;
    	  if (isObject(val)) {
    	    var nodeIsArray = isArray(val);
    	    var nodes = unmodified ? node.nodes : nodeIsArray ? [] : {};
    	    if (nodeIsArray) {
    	      elementRecordsLen = nodes.length;
    	      len = lengthOfArrayLike(val);
    	      for (i = 0; i < len; i++) {
    	        internalizeProperty(val, i, internalize(val, '' + i, reviver, i < elementRecordsLen ? nodes[i] : undefined));
    	      }
    	    } else {
    	      keys = enumerableOwnProperties(val);
    	      len = lengthOfArrayLike(keys);
    	      for (i = 0; i < len; i++) {
    	        P = keys[i];
    	        internalizeProperty(val, P, internalize(val, P, reviver, hasOwn(nodes, P) ? nodes[P] : undefined));
    	      }
    	    }
    	  }
    	  return call(reviver, holder, name, val, context);
    	};
    	var internalizeProperty = function (object, key, value) {
    	  if (DESCRIPTORS) {
    	    var descriptor = getOwnPropertyDescriptor(object, key);
    	    if (descriptor && !descriptor.configurable) return;
    	  }
    	  if (value === undefined) delete object[key];
    	  else createProperty(object, key, value);
    	};
    	var Node = function (value, end, source, nodes) {
    	  this.value = value;
    	  this.end = end;
    	  this.source = source;
    	  this.nodes = nodes;
    	};
    	var Context = function (source, index) {
    	  this.source = source;
    	  this.index = index;
    	};
    	Context.prototype = {
    	  fork: function (nextIndex) {
    	    return new Context(this.source, nextIndex);
    	  },
    	  parse: function () {
    	    var source = this.source;
    	    var i = this.skip(IS_WHITESPACE, this.index);
    	    var fork = this.fork(i);
    	    var chr = at(source, i);
    	    if (exec(IS_NUMBER_START, chr)) return fork.number();
    	    switch (chr) {
    	      case '{':
    	        return fork.object();
    	      case '[':
    	        return fork.array();
    	      case '"':
    	        return fork.string();
    	      case 't':
    	        return fork.keyword(true);
    	      case 'f':
    	        return fork.keyword(false);
    	      case 'n':
    	        return fork.keyword(null);
    	    } throw new SyntaxError('Unexpected character: "' + chr + '" at: ' + i);
    	  },
    	  node: function (type, value, start, end, nodes) {
    	    return new Node(value, end, type ? null : slice(this.source, start, end), nodes);
    	  },
    	  object: function () {
    	    var source = this.source;
    	    var i = this.index + 1;
    	    var expectKeypair = false;
    	    var object = {};
    	    var nodes = {};
    	    var closed = false;
    	    while (i < source.length) {
    	      i = this.until(['"', '}'], i);
    	      if (at(source, i) === '}' && !expectKeypair) {
    	        i++;
    	        closed = true;
    	        break;
    	      }
    	      var result = this.fork(i).string();
    	      var key = result.value;
    	      i = result.end;
    	      i = this.until([':'], i) + 1;
    	      i = this.skip(IS_WHITESPACE, i);
    	      result = this.fork(i).parse();
    	      createProperty(nodes, key, result);
    	      createProperty(object, key, result.value);
    	      i = this.until([',', '}'], result.end);
    	      var chr = at(source, i);
    	      if (chr === ',') {
    	        expectKeypair = true;
    	        i++;
    	      } else if (chr === '}') {
    	        i++;
    	        closed = true;
    	        break;
    	      }
    	    }
    	    if (!closed) throw new SyntaxError('Unterminated object at: ' + i);
    	    return this.node(OBJECT, object, this.index, i, nodes);
    	  },
    	  array: function () {
    	    var source = this.source;
    	    var i = this.index + 1;
    	    var expectElement = false;
    	    var array = [];
    	    var nodes = [];
    	    var closed = false;
    	    while (i < source.length) {
    	      i = this.skip(IS_WHITESPACE, i);
    	      if (at(source, i) === ']' && !expectElement) {
    	        i++;
    	        closed = true;
    	        break;
    	      }
    	      var result = this.fork(i).parse();
    	      push(nodes, result);
    	      push(array, result.value);
    	      i = this.until([',', ']'], result.end);
    	      if (at(source, i) === ',') {
    	        expectElement = true;
    	        i++;
    	      } else if (at(source, i) === ']') {
    	        i++;
    	        closed = true;
    	        break;
    	      }
    	    }
    	    if (!closed) throw new SyntaxError('Unterminated array at: ' + i);
    	    return this.node(OBJECT, array, this.index, i, nodes);
    	  },
    	  string: function () {
    	    var index = this.index;
    	    var parsed = parseJSONString(this.source, this.index + 1);
    	    return this.node(PRIMITIVE, parsed.value, index, parsed.end);
    	  },
    	  number: function () {
    	    var source = this.source;
    	    var startIndex = this.index;
    	    var i = startIndex;
    	    if (at(source, i) === '-') i++;
    	    if (at(source, i) === '0') i++;
    	    else if (exec(IS_NON_ZERO_DIGIT, at(source, i))) i = this.skip(IS_DIGIT, i + 1);
    	    else throw new SyntaxError('Failed to parse number at: ' + i);
    	    if (at(source, i) === '.') {
    	      var fractionStartIndex = i + 1;
    	      i = this.skip(IS_DIGIT, fractionStartIndex);
    	      if (fractionStartIndex === i) throw new SyntaxError("Failed to parse number's fraction at: " + i);
    	    }
    	    if (at(source, i) === 'e' || at(source, i) === 'E') {
    	      i++;
    	      if (at(source, i) === '+' || at(source, i) === '-') i++;
    	      var exponentStartIndex = i;
    	      i = this.skip(IS_DIGIT, i);
    	      if (exponentStartIndex === i) throw new SyntaxError("Failed to parse number's exponent value at: " + i);
    	    }
    	    return this.node(PRIMITIVE, Number(slice(source, startIndex, i)), startIndex, i);
    	  },
    	  keyword: function (value) {
    	    var keyword = '' + value;
    	    var index = this.index;
    	    var endIndex = index + keyword.length;
    	    if (slice(this.source, index, endIndex) !== keyword) throw new SyntaxError('Failed to parse value at: ' + index);
    	    return this.node(PRIMITIVE, value, index, endIndex);
    	  },
    	  skip: function (regex, i) {
    	    var source = this.source;
    	    for (; i < source.length; i++) if (!exec(regex, at(source, i))) break;
    	    return i;
    	  },
    	  until: function (array, i) {
    	    i = this.skip(IS_WHITESPACE, i);
    	    var chr = at(this.source, i);
    	    for (var j = 0; j < array.length; j++) if (array[j] === chr) return i;
    	    throw new SyntaxError('Unexpected character: "' + chr + '" at: ' + i);
    	  }
    	};
    	var NO_SOURCE_SUPPORT = fails(function () {
    	  var unsafeInt = '9007199254740993';
    	  var source;
    	  nativeParse(unsafeInt, function (key, value, context) {
    	    source = context.source;
    	  });
    	  return source !== unsafeInt;
    	});
    	var PROPER_BASE_PARSE = NATIVE_SYMBOL && !fails(function () {
    	  return 1 / nativeParse('-0 \t') !== -Infinity;
    	});
    	$({ target: 'JSON', stat: true, forced: NO_SOURCE_SUPPORT }, {
    	  parse: function parse(text, reviver) {
    	    return PROPER_BASE_PARSE && !isCallable(reviver) ? nativeParse(text) : $parse(text, reviver);
    	  }
    	});
    	return es_json_parse;
    }

    var parse$1;
    var hasRequiredParse$1;
    function requireParse$1 () {
    	if (hasRequiredParse$1) return parse$1;
    	hasRequiredParse$1 = 1;
    	requireEs_object_keys();
    	requireEs_json_parse();
    	var path =  requirePath();
    	parse$1 = path.JSON.parse;
    	return parse$1;
    }

    var parse;
    var hasRequiredParse;
    function requireParse () {
    	if (hasRequiredParse) return parse;
    	hasRequiredParse = 1;
    	var parent =  requireParse$1();
    	parse = parent;
    	return parse;
    }

    var parseExports = /*@__PURE__*/ requireParse();
    var _JSON$parse = /*@__PURE__*/getDefaultExportFromCjs(parseExports);

    var es_date_toJson = {};

    var stringRepeat;
    var hasRequiredStringRepeat;
    function requireStringRepeat () {
    	if (hasRequiredStringRepeat) return stringRepeat;
    	hasRequiredStringRepeat = 1;
    	var toIntegerOrInfinity =  requireToIntegerOrInfinity();
    	var toString =  requireToString();
    	var requireObjectCoercible =  requireRequireObjectCoercible();
    	var $RangeError = RangeError;
    	var floor = Math.floor;
    	stringRepeat = function repeat(count) {
    	  var str = toString(requireObjectCoercible(this));
    	  var result = '';
    	  var n = toIntegerOrInfinity(count);
    	  if (n < 0 || n === Infinity) throw new $RangeError('Wrong number of repetitions');
    	  for (;n > 0; (n = floor(n / 2)) && (str += str)) if (n % 2) result += str;
    	  return result;
    	};
    	return stringRepeat;
    }

    var stringPad;
    var hasRequiredStringPad;
    function requireStringPad () {
    	if (hasRequiredStringPad) return stringPad;
    	hasRequiredStringPad = 1;
    	var uncurryThis =  requireFunctionUncurryThis();
    	var toLength =  requireToLength();
    	var toString =  requireToString();
    	var $repeat =  requireStringRepeat();
    	var requireObjectCoercible =  requireRequireObjectCoercible();
    	var repeat = uncurryThis($repeat);
    	var stringSlice = uncurryThis(''.slice);
    	var ceil = Math.ceil;
    	var createMethod = function (IS_END) {
    	  return function ($this, maxLength, fillString) {
    	    var S = toString(requireObjectCoercible($this));
    	    var intMaxLength = toLength(maxLength);
    	    var stringLength = S.length;
    	    if (intMaxLength <= stringLength) return S;
    	    var fillStr = fillString === undefined ? ' ' : toString(fillString);
    	    var fillLen, stringFiller;
    	    if (fillStr === '') return S;
    	    fillLen = intMaxLength - stringLength;
    	    stringFiller = repeat(fillStr, ceil(fillLen / fillStr.length));
    	    if (stringFiller.length > fillLen) stringFiller = stringSlice(stringFiller, 0, fillLen);
    	    return IS_END ? S + stringFiller : stringFiller + S;
    	  };
    	};
    	stringPad = {
    	  start: createMethod(false),
    	  end: createMethod(true)
    	};
    	return stringPad;
    }

    var dateToIsoString;
    var hasRequiredDateToIsoString;
    function requireDateToIsoString () {
    	if (hasRequiredDateToIsoString) return dateToIsoString;
    	hasRequiredDateToIsoString = 1;
    	var uncurryThis =  requireFunctionUncurryThis();
    	var fails =  requireFails();
    	var padStart =  requireStringPad().start;
    	var $RangeError = RangeError;
    	var $isFinite = isFinite;
    	var abs = Math.abs;
    	var DatePrototype = Date.prototype;
    	var nativeDateToISOString = DatePrototype.toISOString;
    	var thisTimeValue = uncurryThis(DatePrototype.getTime);
    	var getUTCDate = uncurryThis(DatePrototype.getUTCDate);
    	var getUTCFullYear = uncurryThis(DatePrototype.getUTCFullYear);
    	var getUTCHours = uncurryThis(DatePrototype.getUTCHours);
    	var getUTCMilliseconds = uncurryThis(DatePrototype.getUTCMilliseconds);
    	var getUTCMinutes = uncurryThis(DatePrototype.getUTCMinutes);
    	var getUTCMonth = uncurryThis(DatePrototype.getUTCMonth);
    	var getUTCSeconds = uncurryThis(DatePrototype.getUTCSeconds);
    	dateToIsoString = (fails(function () {
    	  return nativeDateToISOString.call(new Date(-5e13 - 1)) !== '0385-07-25T07:06:39.999Z';
    	}) || !fails(function () {
    	  nativeDateToISOString.call(new Date(NaN));
    	})) ? function toISOString() {
    	  if (!$isFinite(thisTimeValue(this))) throw new $RangeError('Invalid time value');
    	  var date = this;
    	  var year = getUTCFullYear(date);
    	  var milliseconds = getUTCMilliseconds(date);
    	  var sign = year < 0 ? '-' : year > 9999 ? '+' : '';
    	  return sign + padStart(abs(year), sign ? 6 : 4, 0) +
    	    '-' + padStart(getUTCMonth(date) + 1, 2, 0) +
    	    '-' + padStart(getUTCDate(date), 2, 0) +
    	    'T' + padStart(getUTCHours(date), 2, 0) +
    	    ':' + padStart(getUTCMinutes(date), 2, 0) +
    	    ':' + padStart(getUTCSeconds(date), 2, 0) +
    	    '.' + padStart(milliseconds, 3, 0) +
    	    'Z';
    	} : nativeDateToISOString;
    	return dateToIsoString;
    }

    var hasRequiredEs_date_toJson;
    function requireEs_date_toJson () {
    	if (hasRequiredEs_date_toJson) return es_date_toJson;
    	hasRequiredEs_date_toJson = 1;
    	var $ =  require_export();
    	var call =  requireFunctionCall();
    	var toObject =  requireToObject();
    	var toPrimitive =  requireToPrimitive();
    	var toISOString =  requireDateToIsoString();
    	var classof =  requireClassofRaw();
    	var fails =  requireFails();
    	var FORCED = fails(function () {
    	  return new Date(NaN).toJSON() !== null
    	    || call(Date.prototype.toJSON, { toISOString: function () { return 1; } }) !== 1;
    	});
    	$({ target: 'Date', proto: true, forced: FORCED }, {
    	  toJSON: function toJSON(key) {
    	    var O = toObject(this);
    	    var pv = toPrimitive(O, 'number');
    	    return typeof pv == 'number' && !isFinite(pv) ? null :
    	      (!('toISOString' in O) && classof(O) === 'Date') ? call(toISOString, O) : O.toISOString();
    	  }
    	});
    	return es_date_toJson;
    }

    var es_json_stringify = {};

    var weakMapBasicDetection;
    var hasRequiredWeakMapBasicDetection;
    function requireWeakMapBasicDetection () {
    	if (hasRequiredWeakMapBasicDetection) return weakMapBasicDetection;
    	hasRequiredWeakMapBasicDetection = 1;
    	var globalThis =  requireGlobalThis();
    	var isCallable =  requireIsCallable();
    	var WeakMap = globalThis.WeakMap;
    	weakMapBasicDetection = isCallable(WeakMap) && /native code/.test(String(WeakMap));
    	return weakMapBasicDetection;
    }

    var sharedKey;
    var hasRequiredSharedKey;
    function requireSharedKey () {
    	if (hasRequiredSharedKey) return sharedKey;
    	hasRequiredSharedKey = 1;
    	var shared =  requireShared();
    	var uid =  requireUid();
    	var keys = shared('keys');
    	sharedKey = function (key) {
    	  return keys[key] || (keys[key] = uid(key));
    	};
    	return sharedKey;
    }

    var internalState;
    var hasRequiredInternalState;
    function requireInternalState () {
    	if (hasRequiredInternalState) return internalState;
    	hasRequiredInternalState = 1;
    	var NATIVE_WEAK_MAP =  requireWeakMapBasicDetection();
    	var globalThis =  requireGlobalThis();
    	var isObject =  requireIsObject();
    	var createNonEnumerableProperty =  requireCreateNonEnumerableProperty();
    	var hasOwn =  requireHasOwnProperty();
    	var shared =  requireSharedStore();
    	var sharedKey =  requireSharedKey();
    	var hiddenKeys =  requireHiddenKeys();
    	var OBJECT_ALREADY_INITIALIZED = 'Object already initialized';
    	var TypeError = globalThis.TypeError;
    	var WeakMap = globalThis.WeakMap;
    	var set, get, has;
    	var enforce = function (it) {
    	  return has(it) ? get(it) : set(it, {});
    	};
    	var getterFor = function (TYPE) {
    	  return function (it) {
    	    var state;
    	    if (!isObject(it) || (state = get(it)).type !== TYPE) {
    	      throw new TypeError('Incompatible receiver, ' + TYPE + ' required');
    	    } return state;
    	  };
    	};
    	if (NATIVE_WEAK_MAP || shared.state) {
    	  var store = shared.state || (shared.state = new WeakMap());
    	  store.get = store.get;
    	  store.has = store.has;
    	  store.set = store.set;
    	  set = function (it, metadata) {
    	    if (store.has(it)) throw new TypeError(OBJECT_ALREADY_INITIALIZED);
    	    metadata.facade = it;
    	    store.set(it, metadata);
    	    return metadata;
    	  };
    	  get = function (it) {
    	    return store.get(it) || {};
    	  };
    	  has = function (it) {
    	    return store.has(it);
    	  };
    	} else {
    	  var STATE = sharedKey('state');
    	  hiddenKeys[STATE] = true;
    	  set = function (it, metadata) {
    	    if (hasOwn(it, STATE)) throw new TypeError(OBJECT_ALREADY_INITIALIZED);
    	    metadata.facade = it;
    	    createNonEnumerableProperty(it, STATE, metadata);
    	    return metadata;
    	  };
    	  get = function (it) {
    	    return hasOwn(it, STATE) ? it[STATE] : {};
    	  };
    	  has = function (it) {
    	    return hasOwn(it, STATE);
    	  };
    	}
    	internalState = {
    	  set: set,
    	  get: get,
    	  has: has,
    	  enforce: enforce,
    	  getterFor: getterFor
    	};
    	return internalState;
    }

    var isRawJson;
    var hasRequiredIsRawJson;
    function requireIsRawJson () {
    	if (hasRequiredIsRawJson) return isRawJson;
    	hasRequiredIsRawJson = 1;
    	var isObject =  requireIsObject();
    	var getInternalState =  requireInternalState().get;
    	isRawJson = function isRawJSON(O) {
    	  if (!isObject(O)) return false;
    	  var state = getInternalState(O);
    	  return !!state && state.type === 'RawJSON';
    	};
    	return isRawJson;
    }

    var arraySlice;
    var hasRequiredArraySlice;
    function requireArraySlice () {
    	if (hasRequiredArraySlice) return arraySlice;
    	hasRequiredArraySlice = 1;
    	var uncurryThis =  requireFunctionUncurryThis();
    	arraySlice = uncurryThis([].slice);
    	return arraySlice;
    }

    var nativeRawJson;
    var hasRequiredNativeRawJson;
    function requireNativeRawJson () {
    	if (hasRequiredNativeRawJson) return nativeRawJson;
    	hasRequiredNativeRawJson = 1;
    	var fails =  requireFails();
    	nativeRawJson = !fails(function () {
    	  var unsafeInt = '9007199254740993';
    	  var raw = JSON.rawJSON(unsafeInt);
    	  return !JSON.isRawJSON(raw) || JSON.stringify(raw) !== unsafeInt;
    	});
    	return nativeRawJson;
    }

    var hasRequiredEs_json_stringify;
    function requireEs_json_stringify () {
    	if (hasRequiredEs_json_stringify) return es_json_stringify;
    	hasRequiredEs_json_stringify = 1;
    	var $ =  require_export();
    	var getBuiltIn =  requireGetBuiltIn();
    	var apply =  requireFunctionApply();
    	var call =  requireFunctionCall();
    	var uncurryThis =  requireFunctionUncurryThis();
    	var fails =  requireFails();
    	var isArray =  requireIsArray();
    	var isCallable =  requireIsCallable();
    	var isRawJSON =  requireIsRawJson();
    	var isSymbol =  requireIsSymbol();
    	var classof =  requireClassofRaw();
    	var toString =  requireToString();
    	var arraySlice =  requireArraySlice();
    	var parseJSONString =  requireParseJsonString();
    	var uid =  requireUid();
    	var NATIVE_SYMBOL =  requireSymbolConstructorDetection();
    	var NATIVE_RAW_JSON =  requireNativeRawJson();
    	var $String = String;
    	var $stringify = getBuiltIn('JSON', 'stringify');
    	var exec = uncurryThis(/./.exec);
    	var charAt = uncurryThis(''.charAt);
    	var charCodeAt = uncurryThis(''.charCodeAt);
    	var replace = uncurryThis(''.replace);
    	var slice = uncurryThis(''.slice);
    	var push = uncurryThis([].push);
    	var numberToString = uncurryThis(1.1.toString);
    	var surrogates = /[\uD800-\uDFFF]/g;
    	var leadingSurrogates = /^[\uD800-\uDBFF]$/;
    	var trailingSurrogates = /^[\uDC00-\uDFFF]$/;
    	var MARK = uid();
    	var MARK_LENGTH = MARK.length;
    	var WRONG_SYMBOLS_CONVERSION = !NATIVE_SYMBOL || fails(function () {
    	  var symbol = getBuiltIn('Symbol')('stringify detection');
    	  return $stringify([symbol]) !== '[null]'
    	    || $stringify({ a: symbol }) !== '{}'
    	    || $stringify(Object(symbol)) !== '{}';
    	});
    	var ILL_FORMED_UNICODE = fails(function () {
    	  return $stringify('\uDF06\uD834') !== '"\\udf06\\ud834"'
    	    || $stringify('\uDEAD') !== '"\\udead"';
    	});
    	var stringifyWithProperSymbolsConversion = WRONG_SYMBOLS_CONVERSION ? function (it, replacer) {
    	  var args = arraySlice(arguments);
    	  var $replacer = getReplacerFunction(replacer);
    	  if (!isCallable($replacer) && (it === undefined || isSymbol(it))) return;
    	  args[1] = function (key, value) {
    	    if (isCallable($replacer)) value = call($replacer, this, $String(key), value);
    	    if (!isSymbol(value)) return value;
    	  };
    	  return apply($stringify, null, args);
    	} : $stringify;
    	var fixIllFormedJSON = function (match, offset, string) {
    	  var prev = charAt(string, offset - 1);
    	  var next = charAt(string, offset + 1);
    	  if (
    	    (exec(leadingSurrogates, match) && !exec(trailingSurrogates, next)) ||
    	    (exec(trailingSurrogates, match) && !exec(leadingSurrogates, prev))
    	  ) {
    	    return '\\u' + numberToString(charCodeAt(match, 0), 16);
    	  } return match;
    	};
    	var getReplacerFunction = function (replacer) {
    	  if (isCallable(replacer)) return replacer;
    	  if (!isArray(replacer)) return;
    	  var rawLength = replacer.length;
    	  var keys = [];
    	  for (var i = 0; i < rawLength; i++) {
    	    var element = replacer[i];
    	    if (typeof element == 'string') push(keys, element);
    	    else if (typeof element == 'number' || classof(element) === 'Number' || classof(element) === 'String') push(keys, toString(element));
    	  }
    	  var keysLength = keys.length;
    	  var root = true;
    	  return function (key, value) {
    	    if (root) {
    	      root = false;
    	      return value;
    	    }
    	    if (isArray(this)) return value;
    	    for (var j = 0; j < keysLength; j++) if (keys[j] === key) return value;
    	  };
    	};
    	if ($stringify) $({ target: 'JSON', stat: true, arity: 3, forced: WRONG_SYMBOLS_CONVERSION || ILL_FORMED_UNICODE || !NATIVE_RAW_JSON }, {
    	  stringify: function stringify(text, replacer, space) {
    	    var replacerFunction = getReplacerFunction(replacer);
    	    var rawStrings = [];
    	    var json = stringifyWithProperSymbolsConversion(text, function (key, value) {
    	      var v = isCallable(replacerFunction) ? call(replacerFunction, this, $String(key), value) : value;
    	      return !NATIVE_RAW_JSON && isRawJSON(v) ? MARK + (push(rawStrings, v.rawJSON) - 1) : v;
    	    }, space);
    	    if (typeof json != 'string') return json;
    	    if (ILL_FORMED_UNICODE) json = replace(json, surrogates, fixIllFormedJSON);
    	    if (NATIVE_RAW_JSON) return json;
    	    var result = '';
    	    var length = json.length;
    	    for (var i = 0; i < length; i++) {
    	      var chr = charAt(json, i);
    	      if (chr === '"') {
    	        var end = parseJSONString(json, ++i).end - 1;
    	        var string = slice(json, i, end);
    	        result += slice(string, 0, MARK_LENGTH) === MARK
    	          ? rawStrings[slice(string, MARK_LENGTH)]
    	          : '"' + string + '"';
    	        i = end;
    	      } else result += chr;
    	    }
    	    return result;
    	  }
    	});
    	return es_json_stringify;
    }

    var stringify$1;
    var hasRequiredStringify$1;
    function requireStringify$1 () {
    	if (hasRequiredStringify$1) return stringify$1;
    	hasRequiredStringify$1 = 1;
    	requireEs_date_toJson();
    	requireEs_json_stringify();
    	var path =  requirePath();
    	var apply =  requireFunctionApply();
    	if (!path.JSON) path.JSON = { stringify: JSON.stringify };
    	stringify$1 = function stringify(it, replacer, space) {
    	  return apply(path.JSON.stringify, null, arguments);
    	};
    	return stringify$1;
    }

    var stringify;
    var hasRequiredStringify;
    function requireStringify () {
    	if (hasRequiredStringify) return stringify;
    	hasRequiredStringify = 1;
    	var parent =  requireStringify$1();
    	stringify = parent;
    	return stringify;
    }

    var stringifyExports = /*@__PURE__*/ requireStringify();
    var _JSON$stringify = /*@__PURE__*/getDefaultExportFromCjs(stringifyExports);

    var es_array_includes = {};

    var addToUnscopables;
    var hasRequiredAddToUnscopables;
    function requireAddToUnscopables () {
    	if (hasRequiredAddToUnscopables) return addToUnscopables;
    	hasRequiredAddToUnscopables = 1;
    	addToUnscopables = function () {  };
    	return addToUnscopables;
    }

    var hasRequiredEs_array_includes;
    function requireEs_array_includes () {
    	if (hasRequiredEs_array_includes) return es_array_includes;
    	hasRequiredEs_array_includes = 1;
    	var $ =  require_export();
    	var $includes =  requireArrayIncludes().includes;
    	var fails =  requireFails();
    	var addToUnscopables =  requireAddToUnscopables();
    	var BROKEN_ON_SPARSE = fails(function () {
    	  return !Array(1).includes();
    	});
    	var BROKEN_ON_SPARSE_WITH_FROM_INDEX = fails(function () {
    	  return [, 1].includes(undefined, 1);
    	});
    	$({ target: 'Array', proto: true, forced: BROKEN_ON_SPARSE || BROKEN_ON_SPARSE_WITH_FROM_INDEX }, {
    	  includes: function includes(el ) {
    	    return $includes(this, el, arguments.length > 1 ? arguments[1] : undefined);
    	  }
    	});
    	addToUnscopables('includes');
    	return es_array_includes;
    }

    var getBuiltInPrototypeMethod;
    var hasRequiredGetBuiltInPrototypeMethod;
    function requireGetBuiltInPrototypeMethod () {
    	if (hasRequiredGetBuiltInPrototypeMethod) return getBuiltInPrototypeMethod;
    	hasRequiredGetBuiltInPrototypeMethod = 1;
    	var globalThis =  requireGlobalThis();
    	var path =  requirePath();
    	getBuiltInPrototypeMethod = function (CONSTRUCTOR, METHOD) {
    	  var Namespace = path[CONSTRUCTOR + 'Prototype'];
    	  var pureMethod = Namespace && Namespace[METHOD];
    	  if (pureMethod) return pureMethod;
    	  var NativeConstructor = globalThis[CONSTRUCTOR];
    	  var NativePrototype = NativeConstructor && NativeConstructor.prototype;
    	  return NativePrototype && NativePrototype[METHOD];
    	};
    	return getBuiltInPrototypeMethod;
    }

    var includes$3;
    var hasRequiredIncludes$3;
    function requireIncludes$3 () {
    	if (hasRequiredIncludes$3) return includes$3;
    	hasRequiredIncludes$3 = 1;
    	requireEs_array_includes();
    	var getBuiltInPrototypeMethod =  requireGetBuiltInPrototypeMethod();
    	includes$3 = getBuiltInPrototypeMethod('Array', 'includes');
    	return includes$3;
    }

    var es_string_includes = {};

    var isRegexp;
    var hasRequiredIsRegexp;
    function requireIsRegexp () {
    	if (hasRequiredIsRegexp) return isRegexp;
    	hasRequiredIsRegexp = 1;
    	var isObject =  requireIsObject();
    	var classof =  requireClassofRaw();
    	var wellKnownSymbol =  requireWellKnownSymbol();
    	var MATCH = wellKnownSymbol('match');
    	isRegexp = function (it) {
    	  var isRegExp;
    	  return isObject(it) && ((isRegExp = it[MATCH]) !== undefined ? !!isRegExp : classof(it) === 'RegExp');
    	};
    	return isRegexp;
    }

    var notARegexp;
    var hasRequiredNotARegexp;
    function requireNotARegexp () {
    	if (hasRequiredNotARegexp) return notARegexp;
    	hasRequiredNotARegexp = 1;
    	var isRegExp =  requireIsRegexp();
    	var $TypeError = TypeError;
    	notARegexp = function (it) {
    	  if (isRegExp(it)) {
    	    throw new $TypeError("The method doesn't accept regular expressions");
    	  } return it;
    	};
    	return notARegexp;
    }

    var correctIsRegexpLogic;
    var hasRequiredCorrectIsRegexpLogic;
    function requireCorrectIsRegexpLogic () {
    	if (hasRequiredCorrectIsRegexpLogic) return correctIsRegexpLogic;
    	hasRequiredCorrectIsRegexpLogic = 1;
    	var wellKnownSymbol =  requireWellKnownSymbol();
    	var MATCH = wellKnownSymbol('match');
    	correctIsRegexpLogic = function (METHOD_NAME) {
    	  var regexp = /./;
    	  try {
    	    '/./'[METHOD_NAME](regexp);
    	  } catch (error1) {
    	    try {
    	      regexp[MATCH] = false;
    	      return '/./'[METHOD_NAME](regexp);
    	    } catch (error2) {  }
    	  } return false;
    	};
    	return correctIsRegexpLogic;
    }

    var hasRequiredEs_string_includes;
    function requireEs_string_includes () {
    	if (hasRequiredEs_string_includes) return es_string_includes;
    	hasRequiredEs_string_includes = 1;
    	var $ =  require_export();
    	var uncurryThis =  requireFunctionUncurryThis();
    	var notARegExp =  requireNotARegexp();
    	var requireObjectCoercible =  requireRequireObjectCoercible();
    	var toString =  requireToString();
    	var correctIsRegExpLogic =  requireCorrectIsRegexpLogic();
    	var stringIndexOf = uncurryThis(''.indexOf);
    	$({ target: 'String', proto: true, forced: !correctIsRegExpLogic('includes') }, {
    	  includes: function includes(searchString ) {
    	    return !!~stringIndexOf(
    	      toString(requireObjectCoercible(this)),
    	      toString(notARegExp(searchString)),
    	      arguments.length > 1 ? arguments[1] : undefined
    	    );
    	  }
    	});
    	return es_string_includes;
    }

    var includes$2;
    var hasRequiredIncludes$2;
    function requireIncludes$2 () {
    	if (hasRequiredIncludes$2) return includes$2;
    	hasRequiredIncludes$2 = 1;
    	requireEs_string_includes();
    	var getBuiltInPrototypeMethod =  requireGetBuiltInPrototypeMethod();
    	includes$2 = getBuiltInPrototypeMethod('String', 'includes');
    	return includes$2;
    }

    var includes$1;
    var hasRequiredIncludes$1;
    function requireIncludes$1 () {
    	if (hasRequiredIncludes$1) return includes$1;
    	hasRequiredIncludes$1 = 1;
    	var isPrototypeOf =  requireObjectIsPrototypeOf();
    	var arrayMethod =  requireIncludes$3();
    	var stringMethod =  requireIncludes$2();
    	var ArrayPrototype = Array.prototype;
    	var StringPrototype = String.prototype;
    	includes$1 = function (it) {
    	  var own = it.includes;
    	  if (it === ArrayPrototype || (isPrototypeOf(ArrayPrototype, it) && own === ArrayPrototype.includes)) return arrayMethod;
    	  if (typeof it == 'string' || it === StringPrototype || (isPrototypeOf(StringPrototype, it) && own === StringPrototype.includes)) {
    	    return stringMethod;
    	  } return own;
    	};
    	return includes$1;
    }

    var includes;
    var hasRequiredIncludes;
    function requireIncludes () {
    	if (hasRequiredIncludes) return includes;
    	hasRequiredIncludes = 1;
    	var parent =  requireIncludes$1();
    	includes = parent;
    	return includes;
    }

    var includesExports = /*@__PURE__*/ requireIncludes();
    var _includesInstanceProperty = /*@__PURE__*/getDefaultExportFromCjs(includesExports);

    /**
     * Encoder interface mode
     * @public
     */
    exports.EncoderIOMode = void 0;
    (function (EncoderIOMode) {
      /**
       * No additional pull-up or pull-down resistors will be applied to the input lines.
       * @public
       */
      EncoderIOMode[EncoderIOMode["PUSH_PULL"] = 1] = "PUSH_PULL";
      /**
       * 2.2kΩ pull-down resistors will be applied to the input lines.
       * @public
       */
      EncoderIOMode[EncoderIOMode["LINE_DRIVER_2K2"] = 2] = "LINE_DRIVER_2K2";
      /**
       * 10kΩ pull-down resistors will be applied to the input lines.
       * @public
       */
      EncoderIOMode[EncoderIOMode["LINE_DRIVER_10K"] = 3] = "LINE_DRIVER_10K";
      /**
       * 2.2kΩ pull-up resistors will be applied to the input lines.
       * @public
       */
      EncoderIOMode[EncoderIOMode["OPEN_COLLECTOR_2K2"] = 4] = "OPEN_COLLECTOR_2K2";
      /**
       * 10kΩ pull-up resistors will be applied to the input lines.
       * @public
       */
      EncoderIOMode[EncoderIOMode["OPEN_COLLECTOR_10K"] = 5] = "OPEN_COLLECTOR_10K";
    })(exports.EncoderIOMode || (exports.EncoderIOMode = {}));
    /**
     * Error codes returned from all API calls via Exceptions.
     * @public
     */
    exports.ErrorCode = void 0;
    (function (ErrorCode) {
      /**
       * Call succeeded.
       * @public
       */
      ErrorCode[ErrorCode["SUCCESS"] = 0] = "SUCCESS";
      /**
       * Not Permitted
       * @public
       */
      ErrorCode[ErrorCode["NOT_PERMITTED"] = 1] = "NOT_PERMITTED";
      /**
       * The specified entity does not exist. This is usually a result of Net or Log API calls.
       * @public
       */
      ErrorCode[ErrorCode["NO_SUCH_ENTITY"] = 2] = "NO_SUCH_ENTITY";
      /**
       * Call has timed out. This can happen for a number of common reasons: Check that the Phidget you are trying to open is plugged in, and that the addressing parameters have been specified correctly. Check that the Phidget is not already open in another program, such as the Phidget Control Panel, or another program you are developing. If your Phidget has a plug or terminal block for external power, ensure it is plugged in and powered. If you are using remote Phidgets, ensure that your computer can access the remote Phidgets using the Phidget Control Panel. If you are using remote Phidgets, ensure you have enabled Server Discovery or added the server corresponding to the Phidget you are trying to open. If you are using Network Server Discovery, try extending the timeout to allow more time for the server to be discovered.
       * @public
       */
      ErrorCode[ErrorCode["TIMEOUT"] = 3] = "TIMEOUT";
      /**
       * Keep Alive Failure
       * @public
       */
      ErrorCode[ErrorCode["KEEP_ALIVE"] = 58] = "KEEP_ALIVE";
      /**
       * The operation was interrupted; either from an error, or because the device was closed.
       * @public
       */
      ErrorCode[ErrorCode["INTERRUPTED"] = 4] = "INTERRUPTED";
      /**
       * IO Issue
       * @public
       */
      ErrorCode[ErrorCode["IO"] = 5] = "IO";
      /**
       * Memory Issue
       * @public
       */
      ErrorCode[ErrorCode["NO_MEMORY"] = 6] = "NO_MEMORY";
      /**
       * Access to the resource (file) is denied. This can happen when enabling logging.
       * @public
       */
      ErrorCode[ErrorCode["ACCESS"] = 7] = "ACCESS";
      /**
       * Address Issue
       * @public
       */
      ErrorCode[ErrorCode["FAULT"] = 8] = "FAULT";
      /**
       * Specified resource is in use. This error code is not normally used.
       * @public
       */
      ErrorCode[ErrorCode["BUSY"] = 9] = "BUSY";
      /**
       * Object Exists
       * @public
       */
      ErrorCode[ErrorCode["EXISTS"] = 10] = "EXISTS";
      /**
       * Object is not a directory
       * @public
       */
      ErrorCode[ErrorCode["IS_NOT_DIRECTORY"] = 11] = "IS_NOT_DIRECTORY";
      /**
       * Object is a directory
       * @public
       */
      ErrorCode[ErrorCode["IS_DIRECTORY"] = 12] = "IS_DIRECTORY";
      /**
       * Invalid or malformed command. This can be caused by sending a command to a device which is not supported in it's current configuration.
       * @public
       */
      ErrorCode[ErrorCode["INVALID"] = 13] = "INVALID";
      /**
       * Too many open files in system
       * @public
       */
      ErrorCode[ErrorCode["TOO_MANY_FILES_SYSTEM"] = 14] = "TOO_MANY_FILES_SYSTEM";
      /**
       * Too many open files
       * @public
       */
      ErrorCode[ErrorCode["TOO_MANY_FILES"] = 15] = "TOO_MANY_FILES";
      /**
       * The provided buffer argument size is too small.
       * @public
       */
      ErrorCode[ErrorCode["NO_SPACE"] = 16] = "NO_SPACE";
      /**
       * File too Big
       * @public
       */
      ErrorCode[ErrorCode["FILE_TOO_BIG"] = 17] = "FILE_TOO_BIG";
      /**
       * Read Only Filesystem
       * @public
       */
      ErrorCode[ErrorCode["READ_ONLY_FILESYSTEM"] = 18] = "READ_ONLY_FILESYSTEM";
      /**
       * Read Only Object
       * @public
       */
      ErrorCode[ErrorCode["READ_ONLY"] = 19] = "READ_ONLY";
      /**
       * This API call is not supported. For Class APIs this means that this API is not supported by this device. This can also mean the API is not supported on this OS, or OS configuration.
       * @public
       */
      ErrorCode[ErrorCode["UNSUPPORTED"] = 20] = "UNSUPPORTED";
      /**
       * One or more of the parameters passed to the function is not accepted by the channel in its current configuration.
       * @public
       */
      ErrorCode[ErrorCode["INVALID_ARGUMENT"] = 21] = "INVALID_ARGUMENT";
      /**
       * Try again
       * @public
       */
      ErrorCode[ErrorCode["TRY_AGAIN"] = 22] = "TRY_AGAIN";
      /**
       * Not Empty
       * @public
       */
      ErrorCode[ErrorCode["NOT_EMPTY"] = 26] = "NOT_EMPTY";
      /**
       * Something unexpected has occured. Enable library logging and have a look at the log, or contact Phidgets support.
       * @public
       */
      ErrorCode[ErrorCode["UNEXPECTED"] = 28] = "UNEXPECTED";
      /**
       * Duplicated request. Can happen with some Net API calls, such as trying to add the same server twice.
       * @public
       */
      ErrorCode[ErrorCode["DUPLICATE"] = 27] = "DUPLICATE";
      /**
       * Bad Credential
       * @public
       */
      ErrorCode[ErrorCode["BAD_PASSWORD"] = 37] = "BAD_PASSWORD";
      /**
       * Network Unavailable
       * @public
       */
      ErrorCode[ErrorCode["NETWORK_UNAVAILABLE"] = 45] = "NETWORK_UNAVAILABLE";
      /**
       * Connection Refused
       * @public
       */
      ErrorCode[ErrorCode["CONNECTION_REFUSED"] = 35] = "CONNECTION_REFUSED";
      /**
       * Connection Reset
       * @public
       */
      ErrorCode[ErrorCode["CONNECTION_RESET"] = 46] = "CONNECTION_RESET";
      /**
       * No route to host
       * @public
       */
      ErrorCode[ErrorCode["HOST_UNREACHABLE"] = 48] = "HOST_UNREACHABLE";
      /**
       * No Such Device
       * @public
       */
      ErrorCode[ErrorCode["NO_SUCH_DEVICE"] = 40] = "NO_SUCH_DEVICE";
      /**
       * A Phidget channel object of the wrong channel class was passed into this API call.
       * @public
       */
      ErrorCode[ErrorCode["WRONG_DEVICE"] = 50] = "WRONG_DEVICE";
      /**
       * Broken Pipe
       * @public
       */
      ErrorCode[ErrorCode["BROKEN_PIPE"] = 41] = "BROKEN_PIPE";
      /**
       * Name Resolution Failure
       * @public
       */
      ErrorCode[ErrorCode["NAME_RESOLUTION_FAILURE"] = 44] = "NAME_RESOLUTION_FAILURE";
      /**
       * The value is unknown. This can happen right after attach, when the value has not yet been received from the Phidget. This can also happen if a device has not yet been configured / enabled. Some properties can only be read back after being set.
       * @public
       */
      ErrorCode[ErrorCode["UNKNOWN_VALUE"] = 51] = "UNKNOWN_VALUE";
      /**
       * This can happen for a number of common reasons. Be sure you are opening the channel before trying to use it. If you are opening the channel, the program may not be waiting for the channel to be attached. If possible use openWaitForAttachment. Otherwise, be sure to check the Attached property of the channel before trying to use it.
       * @public
       */
      ErrorCode[ErrorCode["NOT_ATTACHED"] = 52] = "NOT_ATTACHED";
      /**
       * Invalid or Unexpected Packet
       * @public
       */
      ErrorCode[ErrorCode["INVALID_PACKET"] = 53] = "INVALID_PACKET";
      /**
       * Argument List Too Long
       * @public
       */
      ErrorCode[ErrorCode["TOO_BIG"] = 54] = "TOO_BIG";
      /**
       * Bad Version
       * @public
       */
      ErrorCode[ErrorCode["BAD_VERSION"] = 55] = "BAD_VERSION";
      /**
       * Channel was closed. This can happen if a channel is closed while openWaitForAttachment is waiting.
       * @public
       */
      ErrorCode[ErrorCode["CLOSED"] = 56] = "CLOSED";
      /**
       * Device is not configured enough for this API call. Have a look at the must-set properties for this device and make sure to configure them first.
       * @public
       */
      ErrorCode[ErrorCode["NOT_CONFIGURED"] = 57] = "NOT_CONFIGURED";
      /**
       * End of File
       * @public
       */
      ErrorCode[ErrorCode["END_OF_FILE"] = 31] = "END_OF_FILE";
      /**
       * Failsafe Triggered on this channel. Close and Re-open the channel to resume operation.
       * @public
       */
      ErrorCode[ErrorCode["FAILSAFE"] = 59] = "FAILSAFE";
      /**
       * The value has been measured to be higher than the valid range of the sensor.
       * @public
       */
      ErrorCode[ErrorCode["UNKNOWN_VALUE_HIGH"] = 60] = "UNKNOWN_VALUE_HIGH";
      /**
       * The value has been measured to be lower than the valid range of the sensor.
       * @public
       */
      ErrorCode[ErrorCode["UNKNOWN_VALUE_LOW"] = 61] = "UNKNOWN_VALUE_LOW";
      /**
       * The power supply of your device is outside the acceptable range to allow operation.
       * @public
       */
      ErrorCode[ErrorCode["BAD_POWER"] = 62] = "BAD_POWER";
      /**
       * Something has caused your device to decide it needs to be powered off and on to resume operation.
       * @public
       */
      ErrorCode[ErrorCode["POWER_CYCLE"] = 63] = "POWER_CYCLE";
      /**
       * The hall sensor on your Brushless DC Motor Controller is Improperly Connected
       * @public
       */
      ErrorCode[ErrorCode["HALLSENSOR"] = 64] = "HALLSENSOR";
      /**
       * Current sensor offset outside acceptable bounds. Move the sensor aways from magnetic fields and try again.
       * @public
       */
      ErrorCode[ErrorCode["BADCURRENT"] = 65] = "BADCURRENT";
      /**
       * One or more required connections on the device has been deemed faulty. Check your connections and try again.
       * @public
       */
      ErrorCode[ErrorCode["BADCONNECTION"] = 66] = "BADCONNECTION";
      /**
       * An external device has responded with a NACK response. Evaluate whether this is expected and try again.
       * @public
       */
      ErrorCode[ErrorCode["NACK"] = 67] = "NACK";
      /**
       * An external device has rejected the request. Evaluate whether this is expected and try again.
       * @public
       */
      ErrorCode[ErrorCode["REJECTED"] = 68] = "REJECTED";
    })(exports.ErrorCode || (exports.ErrorCode = {}));
    /**
     * The error code from an Error event
     * @public
     */
    exports.ErrorEventCode = void 0;
    (function (ErrorEventCode) {
      /**
       * Client and Server protocol versions don't match. Ensure that both sides are using the same release of phidget22.
       * @public
       */
      ErrorEventCode[ErrorEventCode["BAD_VERSION"] = 1] = "BAD_VERSION";
      /**
       * Check that the Phidget is not already open in another program, such as the Phidget Control Panel, or another program you are developing.
       * @public
       */
      ErrorEventCode[ErrorEventCode["BUSY"] = 2] = "BUSY";
      /**
       * This could be a network communication issue, an authentication issue (if server password is enabled), or a Device access / hardware issue.
       * @public
       */
      ErrorEventCode[ErrorEventCode["NETWORK"] = 3] = "NETWORK";
      /**
       * An error occured dispatching a command or event.
       * @public
       */
      ErrorEventCode[ErrorEventCode["DISPATCH"] = 4] = "DISPATCH";
      /**
       * A general failure occured - see description for details.
       * @public
       */
      ErrorEventCode[ErrorEventCode["FAILURE"] = 5] = "FAILURE";
      /**
       * An error state has cleared.
       * @public
       */
      ErrorEventCode[ErrorEventCode["SUCCESS"] = 4096] = "SUCCESS";
      /**
       * A sampling overrun happened in firmware.
       * @public
       */
      ErrorEventCode[ErrorEventCode["OVERRUN"] = 4098] = "OVERRUN";
      /**
       * One or more packets were lost.
       * @public
       */
      ErrorEventCode[ErrorEventCode["PACKET_LOST"] = 4099] = "PACKET_LOST";
      /**
       * Variable has wrapped around.
       * @public
       */
      ErrorEventCode[ErrorEventCode["WRAP_AROUND"] = 4100] = "WRAP_AROUND";
      /**
       * Over-temperature condition detected.
       * @public
       */
      ErrorEventCode[ErrorEventCode["OVER_TEMPERATURE"] = 4101] = "OVER_TEMPERATURE";
      /**
       * Over-current condition detected.
       * @public
       */
      ErrorEventCode[ErrorEventCode["OVER_CURRENT"] = 4102] = "OVER_CURRENT";
      /**
       * Out of range condition detected.
       * @public
       */
      ErrorEventCode[ErrorEventCode["OUT_OF_RANGE"] = 4103] = "OUT_OF_RANGE";
      /**
       * Power supply problem detected.
       * @public
       */
      ErrorEventCode[ErrorEventCode["BAD_POWER"] = 4104] = "BAD_POWER";
      /**
       * Saturation condition detected.
       * @public
       */
      ErrorEventCode[ErrorEventCode["SATURATION"] = 4105] = "SATURATION";
      /**
       * Over-voltage condition detected.
       * @public
       */
      ErrorEventCode[ErrorEventCode["OVER_VOLTAGE"] = 4107] = "OVER_VOLTAGE";
      /**
       * Failsafe condition detected.
       * @public
       */
      ErrorEventCode[ErrorEventCode["FAILSAFE_CONDITION"] = 4108] = "FAILSAFE_CONDITION";
      /**
       * Voltage error detected.
       * @public
       */
      ErrorEventCode[ErrorEventCode["VOLTAGE_ERROR"] = 4109] = "VOLTAGE_ERROR";
      /**
       * Energy dump condition detected.
       * @public
       */
      ErrorEventCode[ErrorEventCode["ENERGY_DUMP_CONDITION"] = 4110] = "ENERGY_DUMP_CONDITION";
      /**
       * Motor stall detected.
       * @public
       */
      ErrorEventCode[ErrorEventCode["MOTOR_STALL_CONDITION"] = 4111] = "MOTOR_STALL_CONDITION";
      /**
       * Invalid state detected.
       * @public
       */
      ErrorEventCode[ErrorEventCode["INVALID_STATE_CONDITION"] = 4112] = "INVALID_STATE_CONDITION";
      /**
       * Bad connection detected.
       * @public
       */
      ErrorEventCode[ErrorEventCode["BAD_CONNECTION_CONDITION"] = 4113] = "BAD_CONNECTION_CONDITION";
      /**
       * Measurement is above the valid range.
       * @public
       */
      ErrorEventCode[ErrorEventCode["OUT_OF_RANGE_HIGH_CONDITION"] = 4114] = "OUT_OF_RANGE_HIGH_CONDITION";
      /**
       * Measurement is below the valid range.
       * @public
       */
      ErrorEventCode[ErrorEventCode["OUT_OF_RANGE_LOW_CONDITION"] = 4115] = "OUT_OF_RANGE_LOW_CONDITION";
      /**
       * Fault condition detected.
       * @public
       */
      ErrorEventCode[ErrorEventCode["FAULT"] = 4116] = "FAULT";
      /**
       * External stop condition detected.
       * @public
       */
      ErrorEventCode[ErrorEventCode["ESTOP"] = 4117] = "ESTOP";
      /**
       * Current sensor problem detected.
       * @public
       */
      ErrorEventCode[ErrorEventCode["BAD_CURRENT"] = 4118] = "BAD_CURRENT";
    })(exports.ErrorEventCode || (exports.ErrorEventCode = {}));
    /**
     * Phidget device ID
     * @public
     */
    exports.DeviceID = void 0;
    (function (DeviceID) {
      /**
       * Unknown device
       * @internal
       */
      DeviceID[DeviceID["NONE"] = 0] = "NONE";
      /**
       * Unknown Device
       * @public
       */
      DeviceID[DeviceID["UNKNOWN"] = 125] = "UNKNOWN";
      /**
       * Hub Port - Digital Input mode
       * @public
       */
      DeviceID[DeviceID["DIGITAL_INPUT_PORT"] = 95] = "DIGITAL_INPUT_PORT";
      /**
       * Hub Port - Digital Output mode
       * @public
       */
      DeviceID[DeviceID["DIGITAL_OUTPUT_PORT"] = 96] = "DIGITAL_OUTPUT_PORT";
      /**
       * Hub Port - Voltage Input mode
       * @public
       */
      DeviceID[DeviceID["VOLTAGE_INPUT_PORT"] = 97] = "VOLTAGE_INPUT_PORT";
      /**
       * Hub Port - Voltage Ratio Input mode
       * @public
       */
      DeviceID[DeviceID["VOLTAGE_RATIO_INPUT_PORT"] = 98] = "VOLTAGE_RATIO_INPUT_PORT";
      /**
       * Dictionary
       * @public
       */
      DeviceID[DeviceID["PN_DICTIONARY"] = 111] = "PN_DICTIONARY";
      /**
       * PhidgetServo 1-Motor (1000)
       * @public
       */
      DeviceID[DeviceID["PN_1000"] = 2] = "PN_1000";
      /**
       * PhidgetServo 4-Motor (1001)
       * @public
       */
      DeviceID[DeviceID["PN_1001"] = 3] = "PN_1001";
      /**
       * PhidgetAnalog 4-Output (1002)
       * @public
       */
      DeviceID[DeviceID["PN_1002"] = 4] = "PN_1002";
      /**
       * PhidgetAccelerometer 2-Axis (1008)
       * @public
       */
      DeviceID[DeviceID["PN_1008"] = 5] = "PN_1008";
      /**
       * PhidgetInterfaceKit 8/8/8 (1010, 1013, 1018, 1019)
       * @public
       */
      DeviceID[DeviceID["PN_1010_1013_1018_1019"] = 6] = "PN_1010_1013_1018_1019";
      /**
       * PhidgetInterfaceKit 2/2/2 (1011)
       * @public
       */
      DeviceID[DeviceID["PN_1011"] = 7] = "PN_1011";
      /**
       * PhidgetInterfaceKit 0/16/16 (1012)
       * @public
       */
      DeviceID[DeviceID["PN_1012"] = 8] = "PN_1012";
      /**
       * PhidgetInterfaceKit 0/0/4 (1014)
       * @public
       */
      DeviceID[DeviceID["PN_1014"] = 9] = "PN_1014";
      /**
       * PhidgetLinearTouch (1015)
       * @public
       */
      DeviceID[DeviceID["PN_1015"] = 10] = "PN_1015";
      /**
       * PhidgetCircularTouch (1016)
       * @public
       */
      DeviceID[DeviceID["PN_1016"] = 11] = "PN_1016";
      /**
       * PhidgetInterfaceKit 0/0/8 (1017)
       * @public
       */
      DeviceID[DeviceID["PN_1017"] = 12] = "PN_1017";
      /**
       * PhidgetRFID (1023)
       * @public
       */
      DeviceID[DeviceID["PN_1023"] = 13] = "PN_1023";
      /**
       * PhidgetRFID Read-Write (1024)
       * @public
       */
      DeviceID[DeviceID["PN_1024"] = 14] = "PN_1024";
      /**
       * PhidgetLED-64 (1030)
       * @public
       */
      DeviceID[DeviceID["PN_1030"] = 15] = "PN_1030";
      /**
       * PhidgetLED-64 Advanced (1031)
       * @public
       */
      DeviceID[DeviceID["PN_1031"] = 16] = "PN_1031";
      /**
       * PhidgetLED-64 Advanced (1032)
       * @public
       */
      DeviceID[DeviceID["PN_1032"] = 17] = "PN_1032";
      /**
       * PhidgetGPS (1040)
       * @public
       */
      DeviceID[DeviceID["PN_1040"] = 18] = "PN_1040";
      /**
       * PhidgetSpatial 0/0/3 Basic (1041)
       * @public
       */
      DeviceID[DeviceID["PN_1041"] = 19] = "PN_1041";
      /**
       * PhidgetSpatial 3/3/3 Basic (1042)
       * @public
       */
      DeviceID[DeviceID["PN_1042"] = 20] = "PN_1042";
      /**
       * PhidgetSpatial Precision 0/0/3 High Resolution (1043)
       * @public
       */
      DeviceID[DeviceID["PN_1043"] = 21] = "PN_1043";
      /**
       * PhidgetSpatial Precision 3/3/3 High Resolution (1044)
       * @public
       */
      DeviceID[DeviceID["PN_1044"] = 22] = "PN_1044";
      /**
       * PhidgetTemperatureSensor IR (1045)
       * @public
       */
      DeviceID[DeviceID["PN_1045"] = 23] = "PN_1045";
      /**
       * PhidgetBridge 4-Input (1046)
       * @public
       */
      DeviceID[DeviceID["PN_1046"] = 24] = "PN_1046";
      /**
       * PhidgetEncoder HighSpeed 4-Input (1047)
       * @public
       */
      DeviceID[DeviceID["PN_1047"] = 25] = "PN_1047";
      /**
       * PhidgetTemperatureSensor 4-Input (1048)
       * @public
       */
      DeviceID[DeviceID["PN_1048"] = 26] = "PN_1048";
      /**
       * PhidgetSpatial 0/0/3 (1049)
       * @public
       */
      DeviceID[DeviceID["PN_1049"] = 27] = "PN_1049";
      /**
       * PhidgetTemperatureSensor 1-Input (1051)
       * @public
       */
      DeviceID[DeviceID["PN_1051"] = 28] = "PN_1051";
      /**
       * PhidgetEncoder (1052)
       * @public
       */
      DeviceID[DeviceID["PN_1052"] = 29] = "PN_1052";
      /**
       * PhidgetAccelerometer 2-Axis (1053)
       * @public
       */
      DeviceID[DeviceID["PN_1053"] = 30] = "PN_1053";
      /**
       * PhidgetFrequencyCounter (1054)
       * @public
       */
      DeviceID[DeviceID["PN_1054"] = 31] = "PN_1054";
      /**
       * PhidgetAccelerometer 2-Axis (1054)
       * @internal
       */
      DeviceID[DeviceID["PN_1054_ACCEL"] = 170] = "PN_1054_ACCEL";
      /**
       * PhidgetIR (1055)
       * @public
       */
      DeviceID[DeviceID["PN_1055"] = 32] = "PN_1055";
      /**
       * PhidgetSpatial 3/3/3 (1056)
       * @public
       */
      DeviceID[DeviceID["PN_1056"] = 33] = "PN_1056";
      /**
       * PhidgetEncoder HighSpeed (1057)
       * @public
       */
      DeviceID[DeviceID["PN_1057"] = 34] = "PN_1057";
      /**
       * PhidgetPHSensor (1058)
       * @public
       */
      DeviceID[DeviceID["PN_1058"] = 35] = "PN_1058";
      /**
       * PhidgetAccelerometer 3-Axis (1059)
       * @public
       */
      DeviceID[DeviceID["PN_1059"] = 36] = "PN_1059";
      /**
       * PhidgetMotorControl LV (1060)
       * @public
       */
      DeviceID[DeviceID["PN_1060"] = 37] = "PN_1060";
      /**
       * PhidgetAdvancedServo 8-Motor (1061)
       * @public
       */
      DeviceID[DeviceID["PN_1061"] = 38] = "PN_1061";
      /**
       * PhidgetStepper Unipolar 4-Motor (1062)
       * @public
       */
      DeviceID[DeviceID["PN_1062"] = 39] = "PN_1062";
      /**
       * PhidgetStepper Bipolar 1-Motor (1063)
       * @public
       */
      DeviceID[DeviceID["PN_1063"] = 40] = "PN_1063";
      /**
       * PhidgetMotorControl HC (1064)
       * @public
       */
      DeviceID[DeviceID["PN_1064"] = 41] = "PN_1064";
      /**
       * PhidgetMotorControl 1-Motor (1065)
       * @public
       */
      DeviceID[DeviceID["PN_1065"] = 42] = "PN_1065";
      /**
       * PhidgetAdvancedServo 1-Motor (1066)
       * @public
       */
      DeviceID[DeviceID["PN_1066"] = 43] = "PN_1066";
      /**
       * PhidgetStepper Bipolar HC (1067)
       * @public
       */
      DeviceID[DeviceID["PN_1067"] = 44] = "PN_1067";
      /**
       * PhidgetTextLCD 20x2 with PhidgetInterfaceKit 8/8/8 (1202, 1203)
       * @public
       */
      DeviceID[DeviceID["PN_1202_1203"] = 45] = "PN_1202_1203";
      /**
       * PhidgetTextLCD Adapter (1204)
       * @public
       */
      DeviceID[DeviceID["PN_1204"] = 46] = "PN_1204";
      /**
       * PhidgetTextLCD 20x2 (1215, 1216, 1217, 1218)
       * @public
       */
      DeviceID[DeviceID["PN_1215__1218"] = 47] = "PN_1215__1218";
      /**
       * PhidgetTextLCD 20x2 with PhidgetInterfaceKit 0/8/8 (1219, 1220, 1221, 1222)
       * @public
       */
      DeviceID[DeviceID["PN_1219__1222"] = 48] = "PN_1219__1222";
      /**
       * I2C Adapter Phidget
       * @public
       */
      DeviceID[DeviceID["PN_ADP0001"] = 134] = "PN_ADP0001";
      /**
       * SPI Adapter Phidget
       * @public
       */
      DeviceID[DeviceID["PN_ADP0002"] = 160] = "PN_ADP0002";
      /**
       * pH Adapter Phidget (ADP1000)
       * @public
       */
      DeviceID[DeviceID["PN_ADP1000"] = 49] = "PN_ADP1000";
      /**
       * 8x Voltage Input Phidget (DAQ1000)
       * @public
       */
      DeviceID[DeviceID["PN_DAQ1000"] = 51] = "PN_DAQ1000";
      /**
       * 8x Voltage Input Phidget (DAQ1001)
       * @public
       */
      DeviceID[DeviceID["PN_DAQ1001"] = 157] = "PN_DAQ1001";
      /**
       * 4x Digital Input Phidget (DAQ1200)
       * @public
       */
      DeviceID[DeviceID["PN_DAQ1200"] = 52] = "PN_DAQ1200";
      /**
       * 4x Isolated Digital Input Phidget (DAQ1300)
       * @public
       */
      DeviceID[DeviceID["PN_DAQ1300"] = 53] = "PN_DAQ1300";
      /**
       * 16x Isolated Digital Input Phidget (DAQ1301)
       * @public
       */
      DeviceID[DeviceID["PN_DAQ1301"] = 54] = "PN_DAQ1301";
      /**
       * Versatile Input Phidget (DAQ1400)
       * @public
       */
      DeviceID[DeviceID["PN_DAQ1400"] = 55] = "PN_DAQ1400";
      /**
       * Wheatstone Bridge Phidget (DAQ1500)
       * @public
       */
      DeviceID[DeviceID["PN_DAQ1500"] = 56] = "PN_DAQ1500";
      /**
       * DC Motor Phidget (DCC1000)
       * @public
       */
      DeviceID[DeviceID["PN_DCC1000"] = 57] = "PN_DCC1000";
      /**
       * 2A DC Motor Phidget (DCC1001)
       * @public
       */
      DeviceID[DeviceID["PN_DCC1001"] = 110] = "PN_DCC1001";
      /**
       * 4A DC Motor Phidget (DCC1002)
       * @public
       */
      DeviceID[DeviceID["PN_DCC1002"] = 117] = "PN_DCC1002";
      /**
       * 2x DC Motor Phidget (DCC1003)
       * @public
       */
      DeviceID[DeviceID["PN_DCC1003"] = 120] = "PN_DCC1003";
      /**
       * 30V 50A DC Motor Phidget (DCC1020)
       * @public
       */
      DeviceID[DeviceID["PN_DCC1020"] = 128] = "PN_DCC1020";
      /**
       * 60V 50A DC Motor Phidget (DCC1030)
       * @public
       */
      DeviceID[DeviceID["PN_DCC1030"] = 152] = "PN_DCC1030";
      /**
       * Brushless DC Motor Phidget (DCC1100)
       * @public
       */
      DeviceID[DeviceID["PN_DCC1100"] = 108] = "PN_DCC1100";
      /**
       * 30V 50A Brushless DC Motor Phidget (DCC1120)
       * @public
       */
      DeviceID[DeviceID["PN_DCC1120"] = 150] = "PN_DCC1120";
      /**
       * 60V 50A Brushless DC Motor Phidget (DCC1130)
       * @public
       */
      DeviceID[DeviceID["PN_DCC1130"] = 154] = "PN_DCC1130";
      /**
       * Distance Phidget (DST1000)
       * @public
       */
      DeviceID[DeviceID["PN_DST1000"] = 58] = "PN_DST1000";
      /**
       * Distance Phidget 650mm (DST1001)
       * @public
       */
      DeviceID[DeviceID["PN_DST1001"] = 121] = "PN_DST1001";
      /**
       * Distance Phidget 1300mm (DST1002)
       * @public
       */
      DeviceID[DeviceID["PN_DST1002"] = 126] = "PN_DST1002";
      /**
       * Sonar Phidget (DST1200)
       * @public
       */
      DeviceID[DeviceID["PN_DST1200"] = 59] = "PN_DST1200";
      /**
       * Quadrature Encoder Phidget (ENC1000)
       * @public
       */
      DeviceID[DeviceID["PN_ENC1000"] = 60] = "PN_ENC1000";
      /**
       * Quadrature Encoder Phidget (ENC1001)
       * @public
       */
      DeviceID[DeviceID["PN_ENC1001"] = 155] = "PN_ENC1001";
      /**
       * SPI Phidget in firmware upgrade mode
       * @internal
       */
      DeviceID[DeviceID["FIRMWARE_UPGRADE_SPI"] = 104] = "FIRMWARE_UPGRADE_SPI";
      /**
       * VINT Phidget in firmware upgrade mode, STM32F0 Proc.
       * @internal
       */
      DeviceID[DeviceID["FIRMWARE_UPGRADE_STM32F0"] = 102] = "FIRMWARE_UPGRADE_STM32F0";
      /**
       * VINT Phidget in firmware upgrade mode, STM32F3 Proc.
       * @internal
       */
      DeviceID[DeviceID["FIRMWARE_UPGRADE_STM32F3"] = 145] = "FIRMWARE_UPGRADE_STM32F3";
      /**
       * VINT Phidget in firmware upgrade mode, STM32G0 Proc.
       * @internal
       */
      DeviceID[DeviceID["FIRMWARE_UPGRADE_STM32G0"] = 143] = "FIRMWARE_UPGRADE_STM32G0";
      /**
       * VINT Phidget in firmware upgrade mode, STM8S Proc.
       * @internal
       */
      DeviceID[DeviceID["FIRMWARE_UPGRADE_STM8S"] = 103] = "FIRMWARE_UPGRADE_STM8S";
      /**
       * USB Phidget in firmware upgrade mode
       * @internal
       */
      DeviceID[DeviceID["FIRMWARE_UPGRADE_USB"] = 101] = "FIRMWARE_UPGRADE_USB";
      /**
       * Touch Keypad Phidget (HIN1000)
       * @public
       */
      DeviceID[DeviceID["PN_HIN1000"] = 61] = "PN_HIN1000";
      /**
       * Touch Wheel Phidget (HIN1001)
       * @public
       */
      DeviceID[DeviceID["PN_HIN1001"] = 62] = "PN_HIN1001";
      /**
       * Thumbstick Phidget (HIN1100)
       * @public
       */
      DeviceID[DeviceID["PN_HIN1100"] = 63] = "PN_HIN1100";
      /**
       * Phidget Dial (HIN1101)
       * @public
       */
      DeviceID[DeviceID["PN_HIN1101"] = 109] = "PN_HIN1101";
      /**
       * 6-Port USB VINT Hub Phidget (HUB0000)
       * @public
       */
      DeviceID[DeviceID["PN_HUB0000"] = 64] = "PN_HUB0000";
      /**
       * 6-Port USB VINT Hub Phidget (HUB0001)
       * @public
       */
      DeviceID[DeviceID["PN_HUB0001"] = 142] = "PN_HUB0001";
      /**
       * 6-Port USB VINT Hub Phidget (HUB0002)
       * @public
       */
      DeviceID[DeviceID["PN_HUB0002"] = 147] = "PN_HUB0002";
      /**
       * 6-Port PhidgetSBC VINT Hub Phidget (HUB0004)
       * @public
       */
      DeviceID[DeviceID["PN_HUB0004"] = 67] = "PN_HUB0004";
      /**
       * 1-Port USB VINT Hub Phidget (HUB0007)
       * @public
       */
      DeviceID[DeviceID["PN_HUB0007"] = 148] = "PN_HUB0007";
      /**
       * 6-Port Network VINT Hub Phidget (HUB5000)
       * @public
       */
      DeviceID[DeviceID["PN_HUB5000"] = 123] = "PN_HUB5000";
      /**
       * Humidity Phidget (HUM1000)
       * @public
       */
      DeviceID[DeviceID["PN_HUM1000"] = 69] = "PN_HUM1000";
      /**
       * Humidity Phidget (HUM1001)
       * @public
       */
      DeviceID[DeviceID["PN_HUM1001"] = 127] = "PN_HUM1001";
      /**
       * Soil Moisture Phidget (HUM1100)
       * @public
       */
      DeviceID[DeviceID["PN_HUM1100"] = 136] = "PN_HUM1100";
      /**
       * PhidgetInterfaceKit 4/8/8
       * @internal
       */
      DeviceID[DeviceID["PN_INTERFACE_KIT488"] = 1] = "PN_INTERFACE_KIT488";
      /**
       * Graphic LCD Phidget (LCD1100)
       * @public
       */
      DeviceID[DeviceID["PN_LCD1100"] = 70] = "PN_LCD1100";
      /**
       * Addressable LED Phidget
       * @public
       */
      DeviceID[DeviceID["PN_LED0100"] = 161] = "PN_LED0100";
      /**
       * 32x Isolated LED Phidget (LED1000)
       * @public
       */
      DeviceID[DeviceID["PN_LED1000"] = 71] = "PN_LED1000";
      /**
       * Light Phidget (LUX1000)
       * @public
       */
      DeviceID[DeviceID["PN_LUX1000"] = 72] = "PN_LUX1000";
      /**
       * PhidgetAccelerometer (MOT0100)
       * @public
       */
      DeviceID[DeviceID["PN_MOT0100"] = 146] = "PN_MOT0100";
      /**
       * PhidgetSpatial Precision 3/3/3 (MOT0109)
       * @public
       */
      DeviceID[DeviceID["PN_MOT0109"] = 140] = "PN_MOT0109";
      /**
       * PhidgetSpatial Precision 3/3/3 (MOT0110)
       * @public
       */
      DeviceID[DeviceID["PN_MOT0110"] = 141] = "PN_MOT0110";
      /**
       * Accelerometer Phidget (MOT1100)
       * @public
       */
      DeviceID[DeviceID["PN_MOT1100"] = 73] = "PN_MOT1100";
      /**
       * Spatial Phidget (MOT1101)
       * @public
       */
      DeviceID[DeviceID["PN_MOT1101"] = 74] = "PN_MOT1101";
      /**
       * Spatial Phidget (MOT1102)
       * @public
       */
      DeviceID[DeviceID["PN_MOT1102"] = 137] = "PN_MOT1102";
      /**
       * 12-bit Voltage Output Phidget (OUT1000)
       * @public
       */
      DeviceID[DeviceID["PN_OUT1000"] = 75] = "PN_OUT1000";
      /**
       * Isolated 12-bit Voltage Output Phidget (OUT1001)
       * @public
       */
      DeviceID[DeviceID["PN_OUT1001"] = 76] = "PN_OUT1001";
      /**
       * Isolated 16-bit Voltage Output Phidget (OUT1002)
       * @public
       */
      DeviceID[DeviceID["PN_OUT1002"] = 77] = "PN_OUT1002";
      /**
       * 4x Digital Output Phidget (OUT1100)
       * @public
       */
      DeviceID[DeviceID["PN_OUT1100"] = 78] = "PN_OUT1100";
      /**
       * Barometer Phidget (PRE1000)
       * @public
       */
      DeviceID[DeviceID["PN_PRE1000"] = 79] = "PN_PRE1000";
      /**
       * PhidgetAdvancedServo 8-Motor (RCC0004)
       * @public
       */
      DeviceID[DeviceID["PN_RCC0004"] = 124] = "PN_RCC0004";
      /**
       * 16x RC Servo Phidget (RCC1000)
       * @public
       */
      DeviceID[DeviceID["PN_RCC1000"] = 80] = "PN_RCC1000";
      /**
       * 4x Relay Phidget (REL1000)
       * @public
       */
      DeviceID[DeviceID["PN_REL1000"] = 81] = "PN_REL1000";
      /**
       * 4x Isolated Solid State Relay Phidget (REL1100)
       * @public
       */
      DeviceID[DeviceID["PN_REL1100"] = 82] = "PN_REL1100";
      /**
       * 16x Isolated Solid State Relay Phidget (REL1101)
       * @public
       */
      DeviceID[DeviceID["PN_REL1101"] = 83] = "PN_REL1101";
      /**
       * Programmable Power Guard Phidget (SAF1000)
       * @public
       */
      DeviceID[DeviceID["PN_SAF1000"] = 84] = "PN_SAF1000";
      /**
       * Sound Phidget (SND1000)
       * @public
       */
      DeviceID[DeviceID["PN_SND1000"] = 85] = "PN_SND1000";
      /**
       * Stepper Phidget (STC1000)
       * @public
       */
      DeviceID[DeviceID["PN_STC1000"] = 86] = "PN_STC1000";
      /**
       * 2.5A Stepper Phidget (STC1001)
       * @public
       */
      DeviceID[DeviceID["PN_STC1001"] = 115] = "PN_STC1001";
      /**
       * 8A Stepper Phidget (STC1002)
       * @public
       */
      DeviceID[DeviceID["PN_STC1002"] = 118] = "PN_STC1002";
      /**
       * 4A Stepper Phidget (STC1003)
       * @public
       */
      DeviceID[DeviceID["PN_STC1003"] = 119] = "PN_STC1003";
      /**
       * 4A Stepper Phidget (STC1005)
       * @public
       */
      DeviceID[DeviceID["PN_STC1005"] = 149] = "PN_STC1005";
      /**
       * Temperature Phidget (TMP1000)
       * @public
       */
      DeviceID[DeviceID["PN_TMP1000"] = 87] = "PN_TMP1000";
      /**
       * Isolated Thermocouple Phidget (TMP1100)
       * @public
       */
      DeviceID[DeviceID["PN_TMP1100"] = 88] = "PN_TMP1100";
      /**
       * 4x Thermocouple Phidget (TMP1101)
       * @public
       */
      DeviceID[DeviceID["PN_TMP1101"] = 89] = "PN_TMP1101";
      /**
       * RTD Phidget (TMP1200)
       * @public
       */
      DeviceID[DeviceID["PN_TMP1200"] = 90] = "PN_TMP1200";
      /**
       * RTD Phidget (TMP1202)
       * @public
       */
      DeviceID[DeviceID["PN_TMP1202"] = 158] = "PN_TMP1202";
      /**
       * 20-bit (+-40V) Voltage Input Phidget (VCP1000)
       * @public
       */
      DeviceID[DeviceID["PN_VCP1000"] = 92] = "PN_VCP1000";
      /**
       * 10-bit (+-40V) Voltage Input Phidget (VCP1001)
       * @public
       */
      DeviceID[DeviceID["PN_VCP1001"] = 93] = "PN_VCP1001";
      /**
       * 10-bit (+-1V) Voltage Input Phidget (VCP1002)
       * @public
       */
      DeviceID[DeviceID["PN_VCP1002"] = 94] = "PN_VCP1002";
      /**
       * 30A Current Sensor Phidget (VCP1100)
       * @public
       */
      DeviceID[DeviceID["PN_VCP1100"] = 105] = "PN_VCP1100";
    })(exports.DeviceID || (exports.DeviceID = {}));
    /**
     * Phidget logging level
     * @public
     */
    exports.LogLevel = void 0;
    (function (LogLevel) {
      /**
       * Critical
       * @public
       */
      LogLevel[LogLevel["CRITICAL"] = 1] = "CRITICAL";
      /**
       * Error
       * @public
       */
      LogLevel[LogLevel["ERROR"] = 2] = "ERROR";
      /**
       * Warning
       * @public
       */
      LogLevel[LogLevel["WARNING"] = 3] = "WARNING";
      /**
       * Info
       * @public
       */
      LogLevel[LogLevel["INFO"] = 4] = "INFO";
      /**
       * Debug
       * @public
       */
      LogLevel[LogLevel["DEBUG"] = 5] = "DEBUG";
      /**
       * Verbose
       * @public
       */
      LogLevel[LogLevel["VERBOSE"] = 6] = "VERBOSE";
    })(exports.LogLevel || (exports.LogLevel = {}));
    /**
     * Phidget device class
     * @public
     */
    exports.DeviceClass = void 0;
    (function (DeviceClass) {
      /**
       * Any device
       * @internal
       */
      DeviceClass[DeviceClass["NONE"] = 0] = "NONE";
      /**
       * PhidgetAccelerometer device
       * @public
       */
      DeviceClass[DeviceClass["ACCELEROMETER"] = 1] = "ACCELEROMETER";
      /**
       * PhidgetAdvancedServo device
       * @public
       */
      DeviceClass[DeviceClass["ADVANCED_SERVO"] = 2] = "ADVANCED_SERVO";
      /**
       * PhidgetAnalog device
       * @public
       */
      DeviceClass[DeviceClass["ANALOG"] = 3] = "ANALOG";
      /**
       * PhidgetBridge device
       * @public
       */
      DeviceClass[DeviceClass["BRIDGE"] = 4] = "BRIDGE";
      /**
       * PhidgetCurrentInput device
       * @internal
       */
      DeviceClass[DeviceClass["CURRENT_INPUT"] = 28] = "CURRENT_INPUT";
      /**
       * PhidgetCurrentOutput device
       * @internal
       */
      DeviceClass[DeviceClass["CURRENT_OUTPUT"] = 26] = "CURRENT_OUTPUT";
      /**
       * PhidgetDataAdapter device
       * @public
       */
      DeviceClass[DeviceClass["DATA_ADAPTER"] = 25] = "DATA_ADAPTER";
      /**
       * Dictionary device
       * @public
       */
      DeviceClass[DeviceClass["DICTIONARY"] = 24] = "DICTIONARY";
      /**
       * PhidgetEncoder device
       * @public
       */
      DeviceClass[DeviceClass["ENCODER"] = 5] = "ENCODER";
      /**
       * Phidget device in Firmware Upgrade mode
       * @internal
       */
      DeviceClass[DeviceClass["FIRMWARE_UPGRADE"] = 23] = "FIRMWARE_UPGRADE";
      /**
       * PhidgetFrequencyCounter device
       * @public
       */
      DeviceClass[DeviceClass["FREQUENCY_COUNTER"] = 6] = "FREQUENCY_COUNTER";
      /**
       * PhidgetFrequencyOutput device
       * @internal
       */
      DeviceClass[DeviceClass["FREQUENCY_OUTPUT"] = 27] = "FREQUENCY_OUTPUT";
      /**
       * Generic device
       * @internal
       */
      DeviceClass[DeviceClass["GENERIC"] = 22] = "GENERIC";
      /**
       * PhidgetGPS device
       * @public
       */
      DeviceClass[DeviceClass["GPS"] = 7] = "GPS";
      /**
       * Phidget VINT Hub device
       * @public
       */
      DeviceClass[DeviceClass["HUB"] = 8] = "HUB";
      /**
       * PhidgetInterfaceKit device
       * @public
       */
      DeviceClass[DeviceClass["INTERFACE_KIT"] = 9] = "INTERFACE_KIT";
      /**
       * PhidgetIR device
       * @public
       */
      DeviceClass[DeviceClass["IR"] = 10] = "IR";
      /**
       * PhidgetLED device
       * @public
       */
      DeviceClass[DeviceClass["LED"] = 11] = "LED";
      /**
       * PhidgetLEDArray device
       * @public
       */
      DeviceClass[DeviceClass["LEDARRAY"] = 12] = "LEDARRAY";
      /**
       * PhidgetMotorControl device
       * @public
       */
      DeviceClass[DeviceClass["MOTOR_CONTROL"] = 13] = "MOTOR_CONTROL";
      /**
       * PhidgetPHSensor device
       * @public
       */
      DeviceClass[DeviceClass["PH_SENSOR"] = 14] = "PH_SENSOR";
      /**
       * PhidgetRFID device
       * @public
       */
      DeviceClass[DeviceClass["RFID"] = 15] = "RFID";
      /**
       * PhidgetServo device
       * @public
       */
      DeviceClass[DeviceClass["SERVO"] = 16] = "SERVO";
      /**
       * PhidgetSpatial device
       * @public
       */
      DeviceClass[DeviceClass["SPATIAL"] = 17] = "SPATIAL";
      /**
       * PhidgetStepper device
       * @public
       */
      DeviceClass[DeviceClass["STEPPER"] = 18] = "STEPPER";
      /**
       * PhidgetTemperatureSensor device
       * @public
       */
      DeviceClass[DeviceClass["TEMPERATURE_SENSOR"] = 19] = "TEMPERATURE_SENSOR";
      /**
       * PhidgetTextLCD device
       * @public
       */
      DeviceClass[DeviceClass["TEXT_LCD"] = 20] = "TEXT_LCD";
      /**
       * Phidget VINT device
       * @public
       */
      DeviceClass[DeviceClass["VINT"] = 21] = "VINT";
      /**
       * PhidgetVoltageInput device
       * @internal
       */
      DeviceClass[DeviceClass["PHIDGET_VOLTAGE_INPUT"] = 29] = "PHIDGET_VOLTAGE_INPUT";
    })(exports.DeviceClass || (exports.DeviceClass = {}));
    /**
     * Phidget channel class
     * @public
     */
    exports.ChannelClass = void 0;
    (function (ChannelClass) {
      /**
       * Any channel
       * @internal
       */
      ChannelClass[ChannelClass["NONE"] = 0] = "NONE";
      /**
       * Accelerometer channel
       * @public
       */
      ChannelClass[ChannelClass["ACCELEROMETER"] = 1] = "ACCELEROMETER";
      /**
       * Brushless DC motor channel
       * @public
       */
      ChannelClass[ChannelClass["BLDC_MOTOR"] = 35] = "BLDC_MOTOR";
      /**
       * Capacitive Touch channel
       * @public
       */
      ChannelClass[ChannelClass["CAPACITIVE_TOUCH"] = 14] = "CAPACITIVE_TOUCH";
      /**
       * Current input channel
       * @public
       */
      ChannelClass[ChannelClass["CURRENT_INPUT"] = 2] = "CURRENT_INPUT";
      /**
       * Current output channel
       * @internal
       */
      ChannelClass[ChannelClass["CURRENT_OUTPUT"] = 38] = "CURRENT_OUTPUT";
      /**
       * Data adapter channel
       * @public
       */
      ChannelClass[ChannelClass["DATA_ADAPTER"] = 3] = "DATA_ADAPTER";
      /**
       * DC motor channel
       * @public
       */
      ChannelClass[ChannelClass["DC_MOTOR"] = 4] = "DC_MOTOR";
      /**
       * Dictionary
       * @public
       */
      ChannelClass[ChannelClass["DICTIONARY"] = 36] = "DICTIONARY";
      /**
       * Digital input channel
       * @public
       */
      ChannelClass[ChannelClass["DIGITAL_INPUT"] = 5] = "DIGITAL_INPUT";
      /**
       * Digital output channel
       * @public
       */
      ChannelClass[ChannelClass["DIGITAL_OUTPUT"] = 6] = "DIGITAL_OUTPUT";
      /**
       * Distance sensor channel
       * @public
       */
      ChannelClass[ChannelClass["DISTANCE_SENSOR"] = 7] = "DISTANCE_SENSOR";
      /**
       * Encoder channel
       * @public
       */
      ChannelClass[ChannelClass["ENCODER"] = 8] = "ENCODER";
      /**
       * Firmware upgrade channel
       * @internal
       */
      ChannelClass[ChannelClass["FIRMWARE_UPGRADE"] = 32] = "FIRMWARE_UPGRADE";
      /**
       * Frequency counter channel
       * @public
       */
      ChannelClass[ChannelClass["FREQUENCY_COUNTER"] = 9] = "FREQUENCY_COUNTER";
      /**
       * Generic channel
       * @internal
       */
      ChannelClass[ChannelClass["GENERIC"] = 33] = "GENERIC";
      /**
       * GPS channel
       * @public
       */
      ChannelClass[ChannelClass["GPS"] = 10] = "GPS";
      /**
       * Gyroscope channel
       * @public
       */
      ChannelClass[ChannelClass["GYROSCOPE"] = 12] = "GYROSCOPE";
      /**
       * VINT Hub channel
       * @public
       */
      ChannelClass[ChannelClass["HUB"] = 13] = "HUB";
      /**
       * Humidity sensor channel
       * @public
       */
      ChannelClass[ChannelClass["HUMIDITY_SENSOR"] = 15] = "HUMIDITY_SENSOR";
      /**
       * IR channel
       * @public
       */
      ChannelClass[ChannelClass["IR"] = 16] = "IR";
      /**
       * LCD channel
       * @public
       */
      ChannelClass[ChannelClass["LCD"] = 11] = "LCD";
      /**
       * LED array channel
       * @public
       */
      ChannelClass[ChannelClass["LEDARRAY"] = 19] = "LEDARRAY";
      /**
       * Light sensor channel
       * @public
       */
      ChannelClass[ChannelClass["LIGHT_SENSOR"] = 17] = "LIGHT_SENSOR";
      /**
       * Magnetometer channel
       * @public
       */
      ChannelClass[ChannelClass["MAGNETOMETER"] = 18] = "MAGNETOMETER";
      /**
       * Motor position control channel.
       * @public
       */
      ChannelClass[ChannelClass["MOTOR_POSITION_CONTROLLER"] = 34] = "MOTOR_POSITION_CONTROLLER";
      /**
       * Motor velocity control channel.
       * @public
       */
      ChannelClass[ChannelClass["MOTOR_VELOCITY_CONTROLLER"] = 39] = "MOTOR_VELOCITY_CONTROLLER";
      /**
       * pH sensor channel
       * @public
       */
      ChannelClass[ChannelClass["PH_SENSOR"] = 37] = "PH_SENSOR";
      /**
       * Power guard channel
       * @public
       */
      ChannelClass[ChannelClass["POWER_GUARD"] = 20] = "POWER_GUARD";
      /**
       * Pressure sensor channel
       * @public
       */
      ChannelClass[ChannelClass["PRESSURE_SENSOR"] = 21] = "PRESSURE_SENSOR";
      /**
       * RC Servo channel
       * @public
       */
      ChannelClass[ChannelClass["RC_SERVO"] = 22] = "RC_SERVO";
      /**
       * Resistance input channel
       * @public
       */
      ChannelClass[ChannelClass["RESISTANCE_INPUT"] = 23] = "RESISTANCE_INPUT";
      /**
       * RFID channel
       * @public
       */
      ChannelClass[ChannelClass["RFID"] = 24] = "RFID";
      /**
       * Sound sensor channel
       * @public
       */
      ChannelClass[ChannelClass["SOUND_SENSOR"] = 25] = "SOUND_SENSOR";
      /**
       * Spatial channel
       * @public
       */
      ChannelClass[ChannelClass["SPATIAL"] = 26] = "SPATIAL";
      /**
       * Stepper channel
       * @public
       */
      ChannelClass[ChannelClass["STEPPER"] = 27] = "STEPPER";
      /**
       * Temperature sensor channel
       * @public
       */
      ChannelClass[ChannelClass["TEMPERATURE_SENSOR"] = 28] = "TEMPERATURE_SENSOR";
      /**
       * Voltage input channel
       * @public
       */
      ChannelClass[ChannelClass["VOLTAGE_INPUT"] = 29] = "VOLTAGE_INPUT";
      /**
       * Voltage output channel
       * @public
       */
      ChannelClass[ChannelClass["VOLTAGE_OUTPUT"] = 30] = "VOLTAGE_OUTPUT";
      /**
       * Voltage ratio input channel
       * @public
       */
      ChannelClass[ChannelClass["VOLTAGE_RATIO_INPUT"] = 31] = "VOLTAGE_RATIO_INPUT";
    })(exports.ChannelClass || (exports.ChannelClass = {}));
    /**
     * Phidget channel sub class
     * @public
     */
    exports.ChannelSubclass = void 0;
    (function (ChannelSubclass) {
      /**
       * No subclass
       * @public
       */
      ChannelSubclass[ChannelSubclass["NONE"] = 1] = "NONE";
      /**
       * Digital output duty cycle
       * @public
       */
      ChannelSubclass[ChannelSubclass["DIGITAL_OUTPUT_DUTY_CYCLE"] = 16] = "DIGITAL_OUTPUT_DUTY_CYCLE";
      /**
       * Digital output frequency
       * @public
       */
      ChannelSubclass[ChannelSubclass["DIGITAL_OUTPUT_FREQUENCY"] = 18] = "DIGITAL_OUTPUT_FREQUENCY";
      /**
       * Digital output LED driver
       * @public
       */
      ChannelSubclass[ChannelSubclass["DIGITAL_OUTPUT_LEDDRIVER"] = 17] = "DIGITAL_OUTPUT_LEDDRIVER";
      /**
       * Encoder IO mode settable
       * @public
       */
      ChannelSubclass[ChannelSubclass["ENCODER_MODE_SETTABLE"] = 96] = "ENCODER_MODE_SETTABLE";
      /**
       * Graphic LCD
       * @public
       */
      ChannelSubclass[ChannelSubclass["LCD_GRAPHIC"] = 80] = "LCD_GRAPHIC";
      /**
       * Text LCD
       * @public
       */
      ChannelSubclass[ChannelSubclass["LCD_TEXT"] = 81] = "LCD_TEXT";
      /**
       * RFID NFC
       * @public
       */
      ChannelSubclass[ChannelSubclass["RFID_NFC"] = 128] = "RFID_NFC";
      /**
       * Spatial AHRS/IMU
       * @public
       */
      ChannelSubclass[ChannelSubclass["SPATIAL_AHRS"] = 112] = "SPATIAL_AHRS";
      /**
       * Temperature sensor RTD
       * @public
       */
      ChannelSubclass[ChannelSubclass["TEMPERATURE_SENSOR_RTD"] = 32] = "TEMPERATURE_SENSOR_RTD";
      /**
       * Temperature sensor thermocouple
       * @public
       */
      ChannelSubclass[ChannelSubclass["TEMPERATURE_SENSOR_THERMOCOUPLE"] = 33] = "TEMPERATURE_SENSOR_THERMOCOUPLE";
      /**
       * Voltage sensor port
       * @public
       */
      ChannelSubclass[ChannelSubclass["VOLTAGE_INPUT_SENSOR_PORT"] = 48] = "VOLTAGE_INPUT_SENSOR_PORT";
      /**
       * Voltage ratio bridge input
       * @public
       */
      ChannelSubclass[ChannelSubclass["VOLTAGE_RATIO_INPUT_BRIDGE"] = 65] = "VOLTAGE_RATIO_INPUT_BRIDGE";
      /**
       * Voltage ratio sensor port
       * @public
       */
      ChannelSubclass[ChannelSubclass["VOLTAGE_RATIO_INPUT_SENSOR_PORT"] = 64] = "VOLTAGE_RATIO_INPUT_SENSOR_PORT";
    })(exports.ChannelSubclass || (exports.ChannelSubclass = {}));
    /**
     * The voltage level being provided to the sensor
     * @public
     */
    exports.PowerSupply = void 0;
    (function (PowerSupply) {
      /**
       * Switch the sensor power supply off
       * @public
       */
      PowerSupply[PowerSupply["OFF"] = 1] = "OFF";
      /**
       * The sensor is provided with 12 volts
       * @public
       */
      PowerSupply[PowerSupply["VOLTS_12"] = 2] = "VOLTS_12";
      /**
       * The sensor is provided with 24 volts
       * @public
       */
      PowerSupply[PowerSupply["VOLTS_24"] = 3] = "VOLTS_24";
      /**
       * The sensor is provided with 5 volts
       * @public
       */
      PowerSupply[PowerSupply["VOLTS_5"] = 4] = "VOLTS_5";
    })(exports.PowerSupply || (exports.PowerSupply = {}));
    /**
     * The DataAdapter Voltage
     * @public
     */
    exports.DataAdapterVoltage = void 0;
    (function (DataAdapterVoltage) {
      /**
       * Voltage supplied by external device
       * @public
       */
      DataAdapterVoltage[DataAdapterVoltage["EXTERNAL"] = 1] = "EXTERNAL";
      /**
       * 2.5V
       * @public
       */
      DataAdapterVoltage[DataAdapterVoltage["VOLTS_2_5"] = 3] = "VOLTS_2_5";
      /**
       * 3.3V
       * @public
       */
      DataAdapterVoltage[DataAdapterVoltage["VOLTS_3_3"] = 4] = "VOLTS_3_3";
      /**
       * 5.0V
       * @public
       */
      DataAdapterVoltage[DataAdapterVoltage["VOLTS_5"] = 5] = "VOLTS_5";
    })(exports.DataAdapterVoltage || (exports.DataAdapterVoltage = {}));
    /**
     * RTD wiring configuration
     * @public
     */
    exports.RTDWireSetup = void 0;
    (function (RTDWireSetup) {
      /**
       * Configures the device to make resistance calculations based on a 2-wire RTD setup.
       * @public
       */
      RTDWireSetup[RTDWireSetup["WIRES_2"] = 1] = "WIRES_2";
      /**
       * Configures the device to make resistance calculations based on a 3-wire RTD setup.
       * @public
       */
      RTDWireSetup[RTDWireSetup["WIRES_3"] = 2] = "WIRES_3";
      /**
       * Configures the device to make resistance calculations based on a 4-wire RTD setup.
       * @public
       */
      RTDWireSetup[RTDWireSetup["WIRES_4"] = 3] = "WIRES_4";
    })(exports.RTDWireSetup || (exports.RTDWireSetup = {}));
    /**
     * The selected polarity mode for the digital input
     * @public
     */
    exports.InputMode = void 0;
    (function (InputMode) {
      /**
       * For interfacing NPN digital sensors
       * @public
       */
      InputMode[InputMode["NPN"] = 1] = "NPN";
      /**
       * For interfacing PNP digital sensors
       * @public
       */
      InputMode[InputMode["PNP"] = 2] = "PNP";
      /**
       * Floating input
       * @public
       */
      InputMode[InputMode["FLOATING"] = 3] = "FLOATING";
      /**
       * Enables a pullup for interfaces that only pull low
       * @public
       */
      InputMode[InputMode["PULLUP"] = 4] = "PULLUP";
    })(exports.InputMode || (exports.InputMode = {}));
    /**
     * The operating condition of the fan. Choose between on, off, or automatic (based on temperature).
     * @public
     */
    exports.FanMode = void 0;
    (function (FanMode) {
      /**
       * Turns the fan off.
       * @public
       */
      FanMode[FanMode["OFF"] = 1] = "OFF";
      /**
       * Turns the fan on.
       * @public
       */
      FanMode[FanMode["ON"] = 2] = "ON";
      /**
       * The fan will be automatically controlled based on temperature.
       * @public
       */
      FanMode[FanMode["AUTO"] = 3] = "AUTO";
    })(exports.FanMode || (exports.FanMode = {}));
    /**
     * The drive type selection for the motor
     * @public
     */
    exports.DriveMode = void 0;
    (function (DriveMode) {
      /**
       * Configures the motor for coasting deceleration
       * @public
       */
      DriveMode[DriveMode["COAST"] = 1] = "COAST";
      /**
       * Configures the motor for forced deceleration
       * @public
       */
      DriveMode[DriveMode["FORCED"] = 2] = "FORCED";
    })(exports.DriveMode || (exports.DriveMode = {}));
    /**
     * The position type selection
     * @public
     */
    exports.PositionType = void 0;
    (function (PositionType) {
      /**
       * Configures the controller to use the encoder as a position source
       * @public
       */
      PositionType[PositionType["ENCODER"] = 1] = "ENCODER";
      /**
       * Configures the controller to use the hall-effect sensor as a position source
       * @public
       */
      PositionType[PositionType["HALL_SENSOR"] = 2] = "HALL_SENSOR";
    })(exports.PositionType || (exports.PositionType = {}));
    /**
     * Controls how data from primary and backup spatial sensing chips are used.
     * @public
     */
    exports.SpatialPrecision = void 0;
    (function (SpatialPrecision) {
      /**
       * High precision sensor is used when possible, fallback to low precision sensor.
       * @public
       */
      SpatialPrecision[SpatialPrecision["HYBRID"] = 0] = "HYBRID";
      /**
       * High precision sensor is always used.
       * @public
       */
      SpatialPrecision[SpatialPrecision["HIGH"] = 1] = "HIGH";
      /**
       * Low precision sensor is always used.
       * @public
       */
      SpatialPrecision[SpatialPrecision["LOW"] = 2] = "LOW";
    })(exports.SpatialPrecision || (exports.SpatialPrecision = {}));
    /**
     * Analog sensor units. These correspond to the types of quantities that can be measured by Phidget analog sensors.
     * @public
     */
    exports.Unit = void 0;
    (function (Unit) {
      /**
       * Unitless
       * @public
       */
      Unit[Unit["NONE"] = 0] = "NONE";
      /**
       * Boolean
       * @public
       */
      Unit[Unit["BOOLEAN"] = 1] = "BOOLEAN";
      /**
       * Percent
       * @public
       */
      Unit[Unit["PERCENT"] = 2] = "PERCENT";
      /**
       * Decibel
       * @public
       */
      Unit[Unit["DECIBEL"] = 3] = "DECIBEL";
      /**
       * Millimeter
       * @public
       */
      Unit[Unit["MILLIMETER"] = 4] = "MILLIMETER";
      /**
       * Centimeter
       * @public
       */
      Unit[Unit["CENTIMETER"] = 5] = "CENTIMETER";
      /**
       * Meter
       * @public
       */
      Unit[Unit["METER"] = 6] = "METER";
      /**
       * Gram
       * @public
       */
      Unit[Unit["GRAM"] = 7] = "GRAM";
      /**
       * Kilogram
       * @public
       */
      Unit[Unit["KILOGRAM"] = 8] = "KILOGRAM";
      /**
       * Milliampere
       * @public
       */
      Unit[Unit["MILLIAMPERE"] = 9] = "MILLIAMPERE";
      /**
       * Ampere
       * @public
       */
      Unit[Unit["AMPERE"] = 10] = "AMPERE";
      /**
       * Kilopascal
       * @public
       */
      Unit[Unit["KILOPASCAL"] = 11] = "KILOPASCAL";
      /**
       * Volt
       * @public
       */
      Unit[Unit["VOLT"] = 12] = "VOLT";
      /**
       * Degree Celcius
       * @public
       */
      Unit[Unit["DEGREE_CELCIUS"] = 13] = "DEGREE_CELCIUS";
      /**
       * Lux
       * @public
       */
      Unit[Unit["LUX"] = 14] = "LUX";
      /**
       * Gauss
       * @public
       */
      Unit[Unit["GAUSS"] = 15] = "GAUSS";
      /**
       * pH
       * @public
       */
      Unit[Unit["PH"] = 16] = "PH";
      /**
       * Watt
       * @public
       */
      Unit[Unit["WATT"] = 17] = "WATT";
    })(exports.Unit || (exports.Unit = {}));
    /**
     * Bridge gain amplification setting. Higher gain results in better resolution, but narrower voltage range.
     * @public
     */
    exports.BridgeGain = void 0;
    (function (BridgeGain) {
      /**
       * 1x Amplificaion
       * @public
       */
      BridgeGain[BridgeGain["GAIN_1X"] = 1] = "GAIN_1X";
      /**
       * 2x Amplification
       * @public
       */
      BridgeGain[BridgeGain["GAIN_2X"] = 2] = "GAIN_2X";
      /**
       * 4x Amplification
       * @public
       */
      BridgeGain[BridgeGain["GAIN_4X"] = 3] = "GAIN_4X";
      /**
       * 8x Amplification
       * @public
       */
      BridgeGain[BridgeGain["GAIN_8X"] = 4] = "GAIN_8X";
      /**
       * 16x Amplification
       * @public
       */
      BridgeGain[BridgeGain["GAIN_16X"] = 5] = "GAIN_16X";
      /**
       * 32x Amplification
       * @public
       */
      BridgeGain[BridgeGain["GAIN_32X"] = 6] = "GAIN_32X";
      /**
       * 64x Amplification
       * @public
       */
      BridgeGain[BridgeGain["GAIN_64X"] = 7] = "GAIN_64X";
      /**
       * 128x Amplification
       * @public
       */
      BridgeGain[BridgeGain["GAIN_128X"] = 8] = "GAIN_128X";
    })(exports.BridgeGain || (exports.BridgeGain = {}));
    /**
     * The type of sensor attached to the voltage ratio input
     * @public
     */
    exports.VoltageRatioSensorType = void 0;
    (function (VoltageRatioSensorType) {
      /**
       * Default. Configures the channel to be a generic ratiometric sensor. Unit is volts/volt.
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["VOLTAGE_RATIO"] = 0] = "VOLTAGE_RATIO";
      /**
       * 1101 - IR Distance Adapter, with Sharp Distance Sensor 2D120X (4-30cm)
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_1101_SHARP2D120X"] = 11011] = "PN_1101_SHARP2D120X";
      /**
       * 1101 - IR Distance Adapter, with Sharp Distance Sensor 2Y0A21 (10-80cm)
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_1101_SHARP2Y0A21"] = 11012] = "PN_1101_SHARP2Y0A21";
      /**
       * 1101 - IR Distance Adapter, with Sharp Distance Sensor 2Y0A02 (20-150cm)
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_1101_SHARP2Y0A02"] = 11013] = "PN_1101_SHARP2Y0A02";
      /**
       * 1102 - IR Reflective Sensor 5mm
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_1102"] = 11020] = "PN_1102";
      /**
       * 1103 - IR Reflective Sensor 10cm
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_1103"] = 11030] = "PN_1103";
      /**
       * 1104 - Vibration Sensor
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_1104"] = 11040] = "PN_1104";
      /**
       * 1105 - Light Sensor
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_1105"] = 11050] = "PN_1105";
      /**
       * 1106 - Force Sensor
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_1106"] = 11060] = "PN_1106";
      /**
       * 1107 - Humidity Sensor
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_1107"] = 11070] = "PN_1107";
      /**
       * 1108 - Magnetic Sensor
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_1108"] = 11080] = "PN_1108";
      /**
       * 1109 - Rotation Sensor
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_1109"] = 11090] = "PN_1109";
      /**
       * 1110 - Touch Sensor
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_1110"] = 11100] = "PN_1110";
      /**
       * 1111 - Motion Sensor
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_1111"] = 11110] = "PN_1111";
      /**
       * 1112 - Slider 60
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_1112"] = 11120] = "PN_1112";
      /**
       * 1113 - Mini Joy Stick Sensor
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_1113"] = 11130] = "PN_1113";
      /**
       * 1115 - Pressure Sensor
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_1115"] = 11150] = "PN_1115";
      /**
       * 1116 - Multi-turn Rotation Sensor
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_1116"] = 11160] = "PN_1116";
      /**
       * 1118 - 50Amp Current Sensor AC
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_1118_AC"] = 11181] = "PN_1118_AC";
      /**
       * 1118 - 50Amp Current Sensor DC
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_1118_DC"] = 11182] = "PN_1118_DC";
      /**
       * 1119 - 20Amp Current Sensor AC
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_1119_AC"] = 11191] = "PN_1119_AC";
      /**
       * 1119 - 20Amp Current Sensor DC
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_1119_DC"] = 11192] = "PN_1119_DC";
      /**
       * 1120 - FlexiForce Adapter
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_1120"] = 11200] = "PN_1120";
      /**
       * 1121 - Voltage Divider
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_1121"] = 11210] = "PN_1121";
      /**
       * 1122 - 30 Amp Current Sensor AC
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_1122_AC"] = 11221] = "PN_1122_AC";
      /**
       * 1122 - 30 Amp Current Sensor DC
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_1122_DC"] = 11222] = "PN_1122_DC";
      /**
       * 1124 - Precision Temperature Sensor
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_1124"] = 11240] = "PN_1124";
      /**
       * 1125 - Humidity Sensor
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_1125_HUMIDITY"] = 11251] = "PN_1125_HUMIDITY";
      /**
       * 1125 - Temperature Sensor
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_1125_TEMPERATURE"] = 11252] = "PN_1125_TEMPERATURE";
      /**
       * 1126 - Differential Air Pressure Sensor +- 25kPa
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_1126"] = 11260] = "PN_1126";
      /**
       * 1128 - MaxBotix EZ-1 Sonar Sensor
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_1128"] = 11280] = "PN_1128";
      /**
       * 1129 - Touch Sensor
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_1129"] = 11290] = "PN_1129";
      /**
       * 1131 - Thin Force Sensor
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_1131"] = 11310] = "PN_1131";
      /**
       * 1134 - Switchable Voltage Divider
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_1134"] = 11340] = "PN_1134";
      /**
       * 1136 - Differential Air Pressure Sensor +-2 kPa
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_1136"] = 11360] = "PN_1136";
      /**
       * 1137 - Differential Air Pressure Sensor +-7 kPa
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_1137"] = 11370] = "PN_1137";
      /**
       * 1138 - Differential Air Pressure Sensor 50 kPa
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_1138"] = 11380] = "PN_1138";
      /**
       * 1139 - Differential Air Pressure Sensor 100 kPa
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_1139"] = 11390] = "PN_1139";
      /**
       * 1140 - Absolute Air Pressure Sensor 20-400 kPa
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_1140"] = 11400] = "PN_1140";
      /**
       * 1141 - Absolute Air Pressure Sensor 15-115 kPa
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_1141"] = 11410] = "PN_1141";
      /**
       * 1146 - IR Reflective Sensor 1-4mm
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_1146"] = 11460] = "PN_1146";
      /**
       * 3120 - Compression Load Cell (0-4.5 kg)
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_3120"] = 31200] = "PN_3120";
      /**
       * 3121 - Compression Load Cell (0-11.3 kg)
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_3121"] = 31210] = "PN_3121";
      /**
       * 3122 - Compression Load Cell (0-22.7 kg)
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_3122"] = 31220] = "PN_3122";
      /**
       * 3123 - Compression Load Cell (0-45.3 kg)
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_3123"] = 31230] = "PN_3123";
      /**
       * 3130 - Relative Humidity Sensor
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_3130"] = 31300] = "PN_3130";
      /**
       * 3520 - Sharp Distance Sensor (4-30cm)
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_3520"] = 35200] = "PN_3520";
      /**
       * 3521 - Sharp Distance Sensor (10-80cm)
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_3521"] = 35210] = "PN_3521";
      /**
       * 3522 - Sharp Distance Sensor (20-150cm)
       * @public
       */
      VoltageRatioSensorType[VoltageRatioSensorType["PN_3522"] = 35220] = "PN_3522";
    })(exports.VoltageRatioSensorType || (exports.VoltageRatioSensorType = {}));
    /**
     * The forward voltage setting of the LED
     * @public
     */
    exports.LEDForwardVoltage = void 0;
    (function (LEDForwardVoltage) {
      /**
       * 1.7 V
       * @public
       */
      LEDForwardVoltage[LEDForwardVoltage["VOLTS_1_7"] = 1] = "VOLTS_1_7";
      /**
       * 2.75 V
       * @public
       */
      LEDForwardVoltage[LEDForwardVoltage["VOLTS_2_75"] = 2] = "VOLTS_2_75";
      /**
       * 3.2 V
       * @public
       */
      LEDForwardVoltage[LEDForwardVoltage["VOLTS_3_2"] = 3] = "VOLTS_3_2";
      /**
       * 3.9 V
       * @public
       */
      LEDForwardVoltage[LEDForwardVoltage["VOLTS_3_9"] = 4] = "VOLTS_3_9";
      /**
       * 4.0 V
       * @public
       */
      LEDForwardVoltage[LEDForwardVoltage["VOLTS_4_0"] = 5] = "VOLTS_4_0";
      /**
       * 4.8 V
       * @public
       */
      LEDForwardVoltage[LEDForwardVoltage["VOLTS_4_8"] = 6] = "VOLTS_4_8";
      /**
       * 5.0 V
       * @public
       */
      LEDForwardVoltage[LEDForwardVoltage["VOLTS_5_0"] = 7] = "VOLTS_5_0";
      /**
       * 5.6 V
       * @public
       */
      LEDForwardVoltage[LEDForwardVoltage["VOLTS_5_6"] = 8] = "VOLTS_5_6";
    })(exports.LEDForwardVoltage || (exports.LEDForwardVoltage = {}));
    /**
     * The voltage of the output
     * @public
     */
    exports.OutputVoltage = void 0;
    (function (OutputVoltage) {
      /**
       * Off
       * @public
       */
      OutputVoltage[OutputVoltage["OFF"] = 1] = "OFF";
      /**
       * 3.3 V
       * @public
       */
      OutputVoltage[OutputVoltage["VOLTS_3_3"] = 2] = "VOLTS_3_3";
      /**
       * 5 V
       * @public
       */
      OutputVoltage[OutputVoltage["VOLTS_5"] = 3] = "VOLTS_5";
      /**
       * 12 V
       * @public
       */
      OutputVoltage[OutputVoltage["VOLTS_12"] = 4] = "VOLTS_12";
      /**
       * 24 V
       * @public
       */
      OutputVoltage[OutputVoltage["VOLTS_24"] = 5] = "VOLTS_24";
    })(exports.OutputVoltage || (exports.OutputVoltage = {}));
    /**
     * Voltage supplied to all attached servos
     * @public
     */
    exports.RCServoVoltage = void 0;
    (function (RCServoVoltage) {
      /**
       * Run all servos on 5V DC
       * @public
       */
      RCServoVoltage[RCServoVoltage["VOLTS_5_0"] = 1] = "VOLTS_5_0";
      /**
       * Run all servos on 6V DC
       * @public
       */
      RCServoVoltage[RCServoVoltage["VOLTS_6_0"] = 2] = "VOLTS_6_0";
      /**
       * Run all servos on 7.4V DC
       * @public
       */
      RCServoVoltage[RCServoVoltage["VOLTS_7_4"] = 3] = "VOLTS_7_4";
    })(exports.RCServoVoltage || (exports.RCServoVoltage = {}));
    /**
     * The selected output voltage range
     * @public
     */
    exports.VoltageOutputRange = void 0;
    (function (VoltageOutputRange) {
      /**
       * ±10V DC
       * @public
       */
      VoltageOutputRange[VoltageOutputRange["VOLTS_10"] = 1] = "VOLTS_10";
      /**
       * 0-5V DC
       * @public
       */
      VoltageOutputRange[VoltageOutputRange["VOLTS_5"] = 2] = "VOLTS_5";
    })(exports.VoltageOutputRange || (exports.VoltageOutputRange = {}));
    /**
     * The selected output voltage range
     * @public
     */
    exports.VoltageOutputWaveformShape = void 0;
    (function (VoltageOutputWaveformShape) {
      /**
       * sine
       * @public
       */
      VoltageOutputWaveformShape[VoltageOutputWaveformShape["SINE"] = 1] = "SINE";
      /**
       * sawtooth
       * @public
       */
      VoltageOutputWaveformShape[VoltageOutputWaveformShape["SAWTOOTH"] = 2] = "SAWTOOTH";
      /**
       * triangle
       * @public
       */
      VoltageOutputWaveformShape[VoltageOutputWaveformShape["TRIANGLE"] = 3] = "TRIANGLE";
      /**
       * square
       * @public
       */
      VoltageOutputWaveformShape[VoltageOutputWaveformShape["SQUARE"] = 4] = "SQUARE";
    })(exports.VoltageOutputWaveformShape || (exports.VoltageOutputWaveformShape = {}));
    /**
     * Measurement range of the voltage input. Larger ranges have less resolution.
     * @public
     */
    exports.VoltageRange = void 0;
    (function (VoltageRange) {
      /**
       * Range ±10mV DC
       * @public
       */
      VoltageRange[VoltageRange["MILLIVOLTS_10"] = 1] = "MILLIVOLTS_10";
      /**
       * Range ±40mV DC
       * @public
       */
      VoltageRange[VoltageRange["MILLIVOLTS_40"] = 2] = "MILLIVOLTS_40";
      /**
       * Range ±200mV DC
       * @public
       */
      VoltageRange[VoltageRange["MILLIVOLTS_200"] = 3] = "MILLIVOLTS_200";
      /**
       * Range ±312.5mV DC
       * @public
       */
      VoltageRange[VoltageRange["MILLIVOLTS_312_5"] = 4] = "MILLIVOLTS_312_5";
      /**
       * Range ±400mV DC
       * @public
       */
      VoltageRange[VoltageRange["MILLIVOLTS_400"] = 5] = "MILLIVOLTS_400";
      /**
       * Range ±1000mV DC
       * @public
       */
      VoltageRange[VoltageRange["MILLIVOLTS_1000"] = 6] = "MILLIVOLTS_1000";
      /**
       * Range ±2V DC
       * @public
       */
      VoltageRange[VoltageRange["VOLTS_2"] = 7] = "VOLTS_2";
      /**
       * Range ±5V DC
       * @public
       */
      VoltageRange[VoltageRange["VOLTS_5"] = 8] = "VOLTS_5";
      /**
       * Range ±15V DC
       * @public
       */
      VoltageRange[VoltageRange["VOLTS_15"] = 9] = "VOLTS_15";
      /**
       * Range ±40V DC
       * @public
       */
      VoltageRange[VoltageRange["VOLTS_40"] = 10] = "VOLTS_40";
      /**
       * Auto-range mode changes based on the present voltage measurements.
       * @public
       */
      VoltageRange[VoltageRange["AUTO"] = 11] = "AUTO";
    })(exports.VoltageRange || (exports.VoltageRange = {}));
    /**
     * Type of sensor attached to the voltage input
     * @public
     */
    exports.VoltageSensorType = void 0;
    (function (VoltageSensorType) {
      /**
       * Default. Configures the channel to be a generic voltage sensor. Unit is volts.
       * @public
       */
      VoltageSensorType[VoltageSensorType["VOLTAGE"] = 0] = "VOLTAGE";
      /**
       * 1114 - Temperature Sensor
       * @public
       */
      VoltageSensorType[VoltageSensorType["PN_1114"] = 11140] = "PN_1114";
      /**
       * 1117 - Voltage Sensor
       * @public
       */
      VoltageSensorType[VoltageSensorType["PN_1117"] = 11170] = "PN_1117";
      /**
       * 1123 - Precision Voltage Sensor
       * @public
       */
      VoltageSensorType[VoltageSensorType["PN_1123"] = 11230] = "PN_1123";
      /**
       * 1127 - Precision Light Sensor
       * @public
       */
      VoltageSensorType[VoltageSensorType["PN_1127"] = 11270] = "PN_1127";
      /**
       * 1130 - pH Adapter
       * @public
       */
      VoltageSensorType[VoltageSensorType["PN_1130_PH"] = 11301] = "PN_1130_PH";
      /**
       * 1130 - ORP Adapter
       * @public
       */
      VoltageSensorType[VoltageSensorType["PN_1130_ORP"] = 11302] = "PN_1130_ORP";
      /**
       * 1132 - 4-20mA Adapter
       * @public
       */
      VoltageSensorType[VoltageSensorType["PN_1132"] = 11320] = "PN_1132";
      /**
       * 1133 - Sound Sensor
       * @public
       */
      VoltageSensorType[VoltageSensorType["PN_1133"] = 11330] = "PN_1133";
      /**
       * 1135 - Precision Voltage Sensor
       * @public
       */
      VoltageSensorType[VoltageSensorType["PN_1135"] = 11350] = "PN_1135";
      /**
       * 1142 - Light Sensor 1000 lux
       * @public
       */
      VoltageSensorType[VoltageSensorType["PN_1142"] = 11420] = "PN_1142";
      /**
       * 1143 - Light Sensor 70000 lux
       * @public
       */
      VoltageSensorType[VoltageSensorType["PN_1143"] = 11430] = "PN_1143";
      /**
       * 3500 - AC Current Sensor 10Amp
       * @public
       */
      VoltageSensorType[VoltageSensorType["PN_3500"] = 35000] = "PN_3500";
      /**
       * 3501 - AC Current Sensor 25Amp
       * @public
       */
      VoltageSensorType[VoltageSensorType["PN_3501"] = 35010] = "PN_3501";
      /**
       * 3502 - AC Current Sensor 50Amp
       * @public
       */
      VoltageSensorType[VoltageSensorType["PN_3502"] = 35020] = "PN_3502";
      /**
       * 3503 - AC Current Sensor 100Amp
       * @public
       */
      VoltageSensorType[VoltageSensorType["PN_3503"] = 35030] = "PN_3503";
      /**
       * 3507 - AC Voltage Sensor 0-250V (50Hz)
       * @public
       */
      VoltageSensorType[VoltageSensorType["PN_3507"] = 35070] = "PN_3507";
      /**
       * 3508 - AC Voltage Sensor 0-250V (60Hz)
       * @public
       */
      VoltageSensorType[VoltageSensorType["PN_3508"] = 35080] = "PN_3508";
      /**
       * 3509 - DC Voltage Sensor 0-200V
       * @public
       */
      VoltageSensorType[VoltageSensorType["PN_3509"] = 35090] = "PN_3509";
      /**
       * 3510 - DC Voltage Sensor 0-75V
       * @public
       */
      VoltageSensorType[VoltageSensorType["PN_3510"] = 35100] = "PN_3510";
      /**
       * 3511 - DC Current Sensor 0-10mA
       * @public
       */
      VoltageSensorType[VoltageSensorType["PN_3511"] = 35110] = "PN_3511";
      /**
       * 3512 - DC Current Sensor 0-100mA
       * @public
       */
      VoltageSensorType[VoltageSensorType["PN_3512"] = 35120] = "PN_3512";
      /**
       * 3513 - DC Current Sensor 0-1A
       * @public
       */
      VoltageSensorType[VoltageSensorType["PN_3513"] = 35130] = "PN_3513";
      /**
       * 3514 - AC Active Power Sensor 0-250V*0-30A (50Hz)
       * @public
       */
      VoltageSensorType[VoltageSensorType["PN_3514"] = 35140] = "PN_3514";
      /**
       * 3515 - AC Active Power Sensor 0-250V*0-30A (60Hz)
       * @public
       */
      VoltageSensorType[VoltageSensorType["PN_3515"] = 35150] = "PN_3515";
      /**
       * 3516 - AC Active Power Sensor 0-250V*0-5A (50Hz)
       * @public
       */
      VoltageSensorType[VoltageSensorType["PN_3516"] = 35160] = "PN_3516";
      /**
       * 3517 - AC Active Power Sensor 0-250V*0-5A (60Hz)
       * @public
       */
      VoltageSensorType[VoltageSensorType["PN_3517"] = 35170] = "PN_3517";
      /**
       * 3518 - AC Active Power Sensor 0-110V*0-5A (60Hz)
       * @public
       */
      VoltageSensorType[VoltageSensorType["PN_3518"] = 35180] = "PN_3518";
      /**
       * 3519 - AC Active Power Sensor 0-110V*0-15A (60Hz)
       * @public
       */
      VoltageSensorType[VoltageSensorType["PN_3519"] = 35190] = "PN_3519";
      /**
       * 3584 - 0-50A DC Current Transducer
       * @public
       */
      VoltageSensorType[VoltageSensorType["PN_3584"] = 35840] = "PN_3584";
      /**
       * 3585 - 0-100A DC Current Transducer
       * @public
       */
      VoltageSensorType[VoltageSensorType["PN_3585"] = 35850] = "PN_3585";
      /**
       * 3586 - 0-250A DC Current Transducer
       * @public
       */
      VoltageSensorType[VoltageSensorType["PN_3586"] = 35860] = "PN_3586";
      /**
       * 3587 - +-50A DC Current Transducer
       * @public
       */
      VoltageSensorType[VoltageSensorType["PN_3587"] = 35870] = "PN_3587";
      /**
       * 3588 - +-100A DC Current Transducer
       * @public
       */
      VoltageSensorType[VoltageSensorType["PN_3588"] = 35880] = "PN_3588";
      /**
       * 3589 - +-250A DC Current Transducer
       * @public
       */
      VoltageSensorType[VoltageSensorType["PN_3589"] = 35890] = "PN_3589";
      /**
       * MOT2002 - Motion Sensor Low Sensitivity
       * @public
       */
      VoltageSensorType[VoltageSensorType["PN_MOT2002_LOW"] = 20020] = "PN_MOT2002_LOW";
      /**
       * MOT2002 - Motion Sensor Medium Sensitivity
       * @public
       */
      VoltageSensorType[VoltageSensorType["PN_MOT2002_MED"] = 20021] = "PN_MOT2002_MED";
      /**
       * MOT2002 - Motion Sensor High Sensitivity
       * @public
       */
      VoltageSensorType[VoltageSensorType["PN_MOT2002_HIGH"] = 20022] = "PN_MOT2002_HIGH";
      /**
       * VCP4114 - +-25A DC Current Transducer
       * @public
       */
      VoltageSensorType[VoltageSensorType["PN_VCP4114"] = 41140] = "PN_VCP4114";
      /**
       * VCP4115 - +-75A DC Current Transducer
       * @public
       */
      VoltageSensorType[VoltageSensorType["PN_VCP4115"] = 41150] = "PN_VCP4115";
      /**
       * VCP4116 - +-100A DC Current Transducer
       * @public
       */
      VoltageSensorType[VoltageSensorType["PN_VCP4116"] = 41160] = "PN_VCP4116";
    })(exports.VoltageSensorType || (exports.VoltageSensorType = {}));
    /**
     * The protocol used to encode the tag data
     * @public
     */
    exports.RFIDProtocol = void 0;
    (function (RFIDProtocol) {
      /**
       * EM4100 Series
       * @public
       */
      RFIDProtocol[RFIDProtocol["EM4100"] = 1] = "EM4100";
      /**
       * ISO11785 FDX B
       * @public
       */
      RFIDProtocol[RFIDProtocol["ISO11785_FDX_B"] = 2] = "ISO11785_FDX_B";
      /**
       * PhidgetTAG
       * @public
       */
      RFIDProtocol[RFIDProtocol["PHIDGET_TAG"] = 3] = "PHIDGET_TAG";
      /**
       * HID Generic
       * @public
       */
      RFIDProtocol[RFIDProtocol["HID_GENERIC"] = 4] = "HID_GENERIC";
      /**
       * HID H10301
       * @public
       */
      RFIDProtocol[RFIDProtocol["HID_H10301"] = 5] = "HID_H10301";
    })(exports.RFIDProtocol || (exports.RFIDProtocol = {}));
    /**
     * The chipset of the writable tag
     * @public
     */
    exports.RFIDChipset = void 0;
    (function (RFIDChipset) {
      /**
       * T5577
       * @public
       */
      RFIDChipset[RFIDChipset["T5577"] = 1] = "T5577";
      /**
       * EM4305
       * @public
       */
      RFIDChipset[RFIDChipset["EM4305"] = 2] = "EM4305";
    })(exports.RFIDChipset || (exports.RFIDChipset = {}));
    /**
     * The tag type of the NFC tag
     * @public
     */
    exports.RFIDTagType = void 0;
    (function (RFIDTagType) {
      /**
       * MIFARE Classic 1K
       * @public
       */
      RFIDTagType[RFIDTagType["MIFARE_CLASSIC1K"] = 1] = "MIFARE_CLASSIC1K";
      /**
       * MIFARE Classic 4K
       * @public
       */
      RFIDTagType[RFIDTagType["MIFARE_CLASSIC4K"] = 2] = "MIFARE_CLASSIC4K";
      /**
       * Generic Type 2
       * @public
       */
      RFIDTagType[RFIDTagType["GENERIC_TYPE2"] = 3] = "GENERIC_TYPE2";
      /**
       * MIFARE Ultralight
       * @public
       */
      RFIDTagType[RFIDTagType["MIFARE_ULTRALIGHT"] = 4] = "MIFARE_ULTRALIGHT";
      /**
       * MIFARE Ultralight EV1
       * @public
       */
      RFIDTagType[RFIDTagType["MIFARE_ULTRALIGHT_EV1"] = 5] = "MIFARE_ULTRALIGHT_EV1";
      /**
       * MIFARE Ultralight C
       * @public
       */
      RFIDTagType[RFIDTagType["MIFARE_ULTRALIGHT_C"] = 6] = "MIFARE_ULTRALIGHT_C";
      /**
       * NTAG 213
       * @public
       */
      RFIDTagType[RFIDTagType["NTAG213"] = 7] = "NTAG213";
      /**
       * NTAG 215
       * @public
       */
      RFIDTagType[RFIDTagType["NTAG215"] = 8] = "NTAG215";
      /**
       * NTAG 216
       * @public
       */
      RFIDTagType[RFIDTagType["NTAG216"] = 9] = "NTAG216";
      /**
       * Unsupported
       * @public
       */
      RFIDTagType[RFIDTagType["UNSUPPORTED"] = 255] = "UNSUPPORTED";
    })(exports.RFIDTagType || (exports.RFIDTagType = {}));
    /**
     * The protocol used to encode the tag data
     * @public
     */
    exports.RFIDTNF = void 0;
    (function (RFIDTNF) {
      /**
       * Record is Empty
       * @public
       */
      RFIDTNF[RFIDTNF["EMPTY"] = 0] = "EMPTY";
      /**
       * Record is well known type
       * @public
       */
      RFIDTNF[RFIDTNF["WELL_KNOWN"] = 1] = "WELL_KNOWN";
      /**
       * Record contains a media type
       * @public
       */
      RFIDTNF[RFIDTNF["MIME_MEDIA"] = 2] = "MIME_MEDIA";
      /**
       * Record is ABSOLUTE_URI
       * @public
       */
      RFIDTNF[RFIDTNF["ABSOLUTE_URI"] = 3] = "ABSOLUTE_URI";
      /**
       * Record is EXTERNAL
       * @public
       */
      RFIDTNF[RFIDTNF["EXTERNAL"] = 4] = "EXTERNAL";
      /**
       * Record is unknown, treat payload as binary
       * @public
       */
      RFIDTNF[RFIDTNF["UNKNOWN"] = 5] = "UNKNOWN";
      /**
       * Used in chunked records, same type as previous chunk.
       * @public
       */
      RFIDTNF[RFIDTNF["UNCHANGED"] = 6] = "UNCHANGED";
    })(exports.RFIDTNF || (exports.RFIDTNF = {}));
    /**
     * Controls the AHRS algorithm.
     * @public
     */
    exports.SpatialAlgorithm = void 0;
    (function (SpatialAlgorithm) {
      /**
       * No AHRS algorithm is used.
       * @public
       */
      SpatialAlgorithm[SpatialAlgorithm["NONE"] = 0] = "NONE";
      /**
       * AHRS algorithm, incorporating magnetometer data for yaw correction.
       * @public
       */
      SpatialAlgorithm[SpatialAlgorithm["AHRS"] = 1] = "AHRS";
      /**
       * IMU algorithm, using gyro and accelerometer, but not magnetometer.
       * @public
       */
      SpatialAlgorithm[SpatialAlgorithm["IMU"] = 2] = "IMU";
    })(exports.SpatialAlgorithm || (exports.SpatialAlgorithm = {}));
    /**
     * RTD sensor type
     * @public
     */
    exports.RTDType = void 0;
    (function (RTDType) {
      /**
       * Configures the RTD type as a PT100 with a 3850ppm curve.
       * @public
       */
      RTDType[RTDType["PT100_3850"] = 1] = "PT100_3850";
      /**
       * Configures the RTD type as a PT1000 with a 3850ppm curve.
       * @public
       */
      RTDType[RTDType["PT1000_3850"] = 2] = "PT1000_3850";
      /**
       * Configures the RTD type as a PT100 with a 3920ppm curve.
       * @public
       */
      RTDType[RTDType["PT100_3920"] = 3] = "PT100_3920";
      /**
       * Configures the RTD type as a PT1000 with a 3920ppm curve.
       * @public
       */
      RTDType[RTDType["PT1000_3920"] = 4] = "PT1000_3920";
    })(exports.RTDType || (exports.RTDType = {}));
    /**
     * The type of thermocouple being used
     * @public
     */
    exports.ThermocoupleType = void 0;
    (function (ThermocoupleType) {
      /**
       * Configures the thermocouple input as a J-Type thermocouple.
       * @public
       */
      ThermocoupleType[ThermocoupleType["J"] = 1] = "J";
      /**
       * Configures the thermocouple input as a K-Type thermocouple.
       * @public
       */
      ThermocoupleType[ThermocoupleType["K"] = 2] = "K";
      /**
       * Configures the thermocouple input as a E-Type thermocouple.
       * @public
       */
      ThermocoupleType[ThermocoupleType["E"] = 3] = "E";
      /**
       * Configures the thermocouple input as a T-Type thermocouple.
       * @public
       */
      ThermocoupleType[ThermocoupleType["T"] = 4] = "T";
    })(exports.ThermocoupleType || (exports.ThermocoupleType = {}));
    /**
     * Type of filter used on the frequency input
     * @public
     */
    exports.FrequencyFilterType = void 0;
    (function (FrequencyFilterType) {
      /**
       * Frequency is calculated from the number of times the signal transitions from a negative voltage to a positive voltage and back again.
       * @public
       */
      FrequencyFilterType[FrequencyFilterType["ZERO_CROSSING"] = 1] = "ZERO_CROSSING";
      /**
       * Frequency is calculated from the number of times the signal transitions from a logic false to a logic true and back again.
       * @public
       */
      FrequencyFilterType[FrequencyFilterType["LOGIC_LEVEL"] = 2] = "LOGIC_LEVEL";
    })(exports.FrequencyFilterType || (exports.FrequencyFilterType = {}));
    /**
     * Describes the encoding technique used for the code
     * @public
     */
    exports.IRCodeEncoding = void 0;
    (function (IRCodeEncoding) {
      /**
       * Unknown - the default value
       * @public
       */
      IRCodeEncoding[IRCodeEncoding["UNKNOWN"] = 1] = "UNKNOWN";
      /**
       * Space encoding, or Pulse Distance Modulation
       * @public
       */
      IRCodeEncoding[IRCodeEncoding["SPACE"] = 2] = "SPACE";
      /**
       * Pulse encoding, or Pulse Width Modulation
       * @public
       */
      IRCodeEncoding[IRCodeEncoding["PULSE"] = 3] = "PULSE";
      /**
       * Bi-Phase, or Manchester encoding
       * @public
       */
      IRCodeEncoding[IRCodeEncoding["BI_PHASE"] = 4] = "BI_PHASE";
      /**
       * RC5 - a type of Bi-Phase encoding
       * @public
       */
      IRCodeEncoding[IRCodeEncoding["RC5"] = 5] = "RC5";
      /**
       * RC6 - a type of Bi-Phase encoding
       * @public
       */
      IRCodeEncoding[IRCodeEncoding["RC6"] = 6] = "RC6";
    })(exports.IRCodeEncoding || (exports.IRCodeEncoding = {}));
    /**
     * The length type of the bitstream and gaps
     * @public
     */
    exports.IRCodeLength = void 0;
    (function (IRCodeLength) {
      /**
       * Unknown - the default value
       * @public
       */
      IRCodeLength[IRCodeLength["UNKNOWN"] = 1] = "UNKNOWN";
      /**
       * Constant - the bitstream and gap length is constant
       * @public
       */
      IRCodeLength[IRCodeLength["CONSTANT"] = 2] = "CONSTANT";
      /**
       * Variable - the bitstream has a variable length with a constant gap
       * @public
       */
      IRCodeLength[IRCodeLength["VARIABLE"] = 3] = "VARIABLE";
    })(exports.IRCodeLength || (exports.IRCodeLength = {}));
    /**
     * Method of motor control
     * @public
     */
    exports.StepperControlMode = void 0;
    (function (StepperControlMode) {
      /**
       * Control the motor by setting a target position.
       * @public
       */
      StepperControlMode[StepperControlMode["STEP"] = 0] = "STEP";
      /**
       * Control the motor by selecting a target velocity (sign indicates direction). The motor will rotate continuously in the chosen direction.
       * @public
       */
      StepperControlMode[StepperControlMode["RUN"] = 1] = "RUN";
    })(exports.StepperControlMode || (exports.StepperControlMode = {}));
    /**
     * The type of font being used
     * @public
     */
    exports.LCDFont = void 0;
    (function (LCDFont) {
      /**
       * User-defined font #1
       * @public
       */
      LCDFont[LCDFont["USER1"] = 1] = "USER1";
      /**
       * User-defined font #2
       * @public
       */
      LCDFont[LCDFont["USER2"] = 2] = "USER2";
      /**
       * 6px by 10px font
       * @public
       */
      LCDFont[LCDFont["DIMENSIONS_6X10"] = 3] = "DIMENSIONS_6X10";
      /**
       * 5px by 8px font
       * @public
       */
      LCDFont[LCDFont["DIMENSIONS_5X8"] = 4] = "DIMENSIONS_5X8";
      /**
       * 6px by 12px font
       * @public
       */
      LCDFont[LCDFont["DIMENSIONS_6X12"] = 5] = "DIMENSIONS_6X12";
    })(exports.LCDFont || (exports.LCDFont = {}));
    /**
     * Size of the attached LCD screen
     * @public
     */
    exports.LCDScreenSize = void 0;
    (function (LCDScreenSize) {
      /**
       * Screen size unknown
       * @public
       */
      LCDScreenSize[LCDScreenSize["NO_SCREEN"] = 1] = "NO_SCREEN";
      /**
       * One row, eight column text screen
       * @public
       */
      LCDScreenSize[LCDScreenSize["DIMENSIONS_1X8"] = 2] = "DIMENSIONS_1X8";
      /**
       * Two row, eight column text screen
       * @public
       */
      LCDScreenSize[LCDScreenSize["DIMENSIONS_2X8"] = 3] = "DIMENSIONS_2X8";
      /**
       * One row, 16 column text screen
       * @public
       */
      LCDScreenSize[LCDScreenSize["DIMENSIONS_1X16"] = 4] = "DIMENSIONS_1X16";
      /**
       * Two row, 16 column text screen
       * @public
       */
      LCDScreenSize[LCDScreenSize["DIMENSIONS_2X16"] = 5] = "DIMENSIONS_2X16";
      /**
       * Four row, 16 column text screen
       * @public
       */
      LCDScreenSize[LCDScreenSize["DIMENSIONS_4X16"] = 6] = "DIMENSIONS_4X16";
      /**
       * Two row, 20 column text screen
       * @public
       */
      LCDScreenSize[LCDScreenSize["DIMENSIONS_2X20"] = 7] = "DIMENSIONS_2X20";
      /**
       * Four row, 20 column text screen.
       * @public
       */
      LCDScreenSize[LCDScreenSize["DIMENSIONS_4X20"] = 8] = "DIMENSIONS_4X20";
      /**
       * Two row, 24 column text screen
       * @public
       */
      LCDScreenSize[LCDScreenSize["DIMENSIONS_2X24"] = 9] = "DIMENSIONS_2X24";
      /**
       * One row, 40 column text screen
       * @public
       */
      LCDScreenSize[LCDScreenSize["DIMENSIONS_1X40"] = 10] = "DIMENSIONS_1X40";
      /**
       * Two row, 40 column text screen
       * @public
       */
      LCDScreenSize[LCDScreenSize["DIMENSIONS_2X40"] = 11] = "DIMENSIONS_2X40";
      /**
       * Four row, 40 column text screen
       * @public
       */
      LCDScreenSize[LCDScreenSize["DIMENSIONS_4X40"] = 12] = "DIMENSIONS_4X40";
      /**
       * 64px by 128px graphic screen
       * @public
       */
      LCDScreenSize[LCDScreenSize["DIMENSIONS_64X128"] = 13] = "DIMENSIONS_64X128";
    })(exports.LCDScreenSize || (exports.LCDScreenSize = {}));
    /**
     * The on/off state of the pixel to be set
     * @public
     */
    exports.LCDPixelState = void 0;
    (function (LCDPixelState) {
      /**
       * Pixel off state
       * @public
       */
      LCDPixelState[LCDPixelState["OFF"] = 0] = "OFF";
      /**
       * Pixel on state
       * @public
       */
      LCDPixelState[LCDPixelState["ON"] = 1] = "ON";
      /**
       * Invert the pixel state
       * @public
       */
      LCDPixelState[LCDPixelState["INVERT"] = 2] = "INVERT";
    })(exports.LCDPixelState || (exports.LCDPixelState = {}));
    /**
     * The SPI Mode
     * @public
     */
    exports.DataAdapterSPIMode = void 0;
    (function (DataAdapterSPIMode) {
      /**
       * CPOL = 0 CPHA = 0
       * @public
       */
      DataAdapterSPIMode[DataAdapterSPIMode["MODE_0"] = 1] = "MODE_0";
      /**
       * CPOL = 0 CPHA = 1
       * @public
       */
      DataAdapterSPIMode[DataAdapterSPIMode["MODE_1"] = 2] = "MODE_1";
      /**
       * CPOL = 1 CPHA = 0
       * @public
       */
      DataAdapterSPIMode[DataAdapterSPIMode["MODE_2"] = 3] = "MODE_2";
      /**
       * CPOL = 1 CPHA = 1
       * @public
       */
      DataAdapterSPIMode[DataAdapterSPIMode["MODE_3"] = 4] = "MODE_3";
    })(exports.DataAdapterSPIMode || (exports.DataAdapterSPIMode = {}));
    /**
     * The communication frequency
     * @public
     */
    exports.DataAdapterFrequency = void 0;
    (function (DataAdapterFrequency) {
      /**
       * 10kHz communication frequency
       * @public
       */
      DataAdapterFrequency[DataAdapterFrequency["FREQUENCY_10K_HZ"] = 1] = "FREQUENCY_10K_HZ";
      /**
       * 100kHz communication frequency
       * @public
       */
      DataAdapterFrequency[DataAdapterFrequency["FREQUENCY_100K_HZ"] = 2] = "FREQUENCY_100K_HZ";
      /**
       * 400kHz communication frequency
       * @public
       */
      DataAdapterFrequency[DataAdapterFrequency["FREQUENCY_400K_HZ"] = 3] = "FREQUENCY_400K_HZ";
      /**
       * 187.5kHz communication frequency
       * @public
       */
      DataAdapterFrequency[DataAdapterFrequency["FREQUENCY_188K_HZ"] = 4] = "FREQUENCY_188K_HZ";
      /**
       * 375kHz communication frequency
       * @public
       */
      DataAdapterFrequency[DataAdapterFrequency["FREQUENCY_375K_HZ"] = 5] = "FREQUENCY_375K_HZ";
      /**
       * 750kHz communication frequency
       * @public
       */
      DataAdapterFrequency[DataAdapterFrequency["FREQUENCY_750K_HZ"] = 6] = "FREQUENCY_750K_HZ";
      /**
       * 1500kHz communication frequency
       * @public
       */
      DataAdapterFrequency[DataAdapterFrequency["FREQUENCY_1500K_HZ"] = 7] = "FREQUENCY_1500K_HZ";
      /**
       * 3MHz communication frequency
       * @public
       */
      DataAdapterFrequency[DataAdapterFrequency["FREQUENCY_3MHZ"] = 8] = "FREQUENCY_3MHZ";
      /**
       * 6MHz communication frequency
       * @public
       */
      DataAdapterFrequency[DataAdapterFrequency["FREQUENCY_6MHZ"] = 9] = "FREQUENCY_6MHZ";
    })(exports.DataAdapterFrequency || (exports.DataAdapterFrequency = {}));
    /**
     * The Type of Error on the Packet
     * @public
     */
    exports.PacketErrorCode = void 0;
    (function (PacketErrorCode) {
      /**
       * No error
       * @public
       */
      PacketErrorCode[PacketErrorCode["OK"] = 0] = "OK";
      /**
       * Unknown Error
       * @public
       */
      PacketErrorCode[PacketErrorCode["UNKNOWN"] = 1] = "UNKNOWN";
      /**
       * The response packet timed out
       * @public
       */
      PacketErrorCode[PacketErrorCode["TIMEOUT"] = 2] = "TIMEOUT";
      /**
       * Something about the sent or received data didn't match the expected format.
       * @public
       */
      PacketErrorCode[PacketErrorCode["FORMAT"] = 3] = "FORMAT";
      /**
       * The input lines are invalid. This likely means a cable has been unplugged.
       * @public
       */
      PacketErrorCode[PacketErrorCode["INVALID"] = 4] = "INVALID";
      /**
       * Data is being received faster than it can be processed. Some has been lost.
       * @public
       */
      PacketErrorCode[PacketErrorCode["OVERRUN"] = 5] = "OVERRUN";
      /**
       * Something behind the scenes got out of sequence.
       * @public
       */
      PacketErrorCode[PacketErrorCode["CORRUPT"] = 6] = "CORRUPT";
      /**
       * One or more packets have received a NACK response
       * @public
       */
      PacketErrorCode[PacketErrorCode["NACK"] = 7] = "NACK";
    })(exports.PacketErrorCode || (exports.PacketErrorCode = {}));
    /**
     * The SPI Chip Select
     * @public
     */
    exports.DataAdapterSPIChipSelect = void 0;
    (function (DataAdapterSPIChipSelect) {
      /**
       * CS normally HIGH, Automatically goes LOW during transmission
       * @public
       */
      DataAdapterSPIChipSelect[DataAdapterSPIChipSelect["ACTIVE_LOW"] = 1] = "ACTIVE_LOW";
      /**
       * CS normally LOW, Automatically goes HIGH during transmission
       * @public
       */
      DataAdapterSPIChipSelect[DataAdapterSPIChipSelect["ACTIVE_HIGH"] = 2] = "ACTIVE_HIGH";
      /**
       * CS is held LOW as long as this is set
       * @public
       */
      DataAdapterSPIChipSelect[DataAdapterSPIChipSelect["LOW"] = 3] = "LOW";
      /**
       * CS is held HIGH as long as this is set
       * @public
       */
      DataAdapterSPIChipSelect[DataAdapterSPIChipSelect["HIGH"] = 4] = "HIGH";
    })(exports.DataAdapterSPIChipSelect || (exports.DataAdapterSPIChipSelect = {}));
    /**
     * The endianness of data being transmitted
     * @public
     */
    exports.DataAdapterEndianness = void 0;
    (function (DataAdapterEndianness) {
      /**
       * MSB First
       * @public
       */
      DataAdapterEndianness[DataAdapterEndianness["MSB_FIRST"] = 1] = "MSB_FIRST";
      /**
       * LSB First
       * @public
       */
      DataAdapterEndianness[DataAdapterEndianness["LSB_FIRST"] = 2] = "LSB_FIRST";
    })(exports.DataAdapterEndianness || (exports.DataAdapterEndianness = {}));
    /**
     * The parity of the data being transmitted
     * @public
     */
    exports.DataAdapterParity = void 0;
    (function (DataAdapterParity) {
      /**
       * None
       * @public
       */
      DataAdapterParity[DataAdapterParity["NONE"] = 1] = "NONE";
      /**
       * Even
       * @public
       */
      DataAdapterParity[DataAdapterParity["EVEN"] = 2] = "EVEN";
      /**
       * Odd
       * @public
       */
      DataAdapterParity[DataAdapterParity["ODD"] = 3] = "ODD";
    })(exports.DataAdapterParity || (exports.DataAdapterParity = {}));
    /**
     * Modbus function codes for coil, register, and diagnostic operations
     * @public
     */
    exports.DataAdapterModbusFunction = void 0;
    (function (DataAdapterModbusFunction) {
      /**
       * Read coils (FC01)
       * @public
       */
      DataAdapterModbusFunction[DataAdapterModbusFunction["READ_COILS"] = 1] = "READ_COILS";
      /**
       * Read discrete inputs (FC02)
       * @public
       */
      DataAdapterModbusFunction[DataAdapterModbusFunction["DISCRETE_INPUT_READ"] = 2] = "DISCRETE_INPUT_READ";
      /**
       * Read holding registers (FC03)
       * @public
       */
      DataAdapterModbusFunction[DataAdapterModbusFunction["READ_REGISTERS_HOLDING"] = 3] = "READ_REGISTERS_HOLDING";
      /**
       * Read input registers (FC04)
       * @public
       */
      DataAdapterModbusFunction[DataAdapterModbusFunction["READ_REGISTERS_INPUT"] = 4] = "READ_REGISTERS_INPUT";
      /**
       * Write single coil (FC05)
       * @public
       */
      DataAdapterModbusFunction[DataAdapterModbusFunction["WRITE_COILS_SINGLE"] = 5] = "WRITE_COILS_SINGLE";
      /**
       * Write single register (FC06)
       * @public
       */
      DataAdapterModbusFunction[DataAdapterModbusFunction["WRITE_REGISTERS_SINGLE"] = 6] = "WRITE_REGISTERS_SINGLE";
      /**
       * Write multiple coils (FC15)
       * @public
       */
      DataAdapterModbusFunction[DataAdapterModbusFunction["WRITE_COILS_MULTIPLE"] = 15] = "WRITE_COILS_MULTIPLE";
      /**
       * Write multiple registers (FC16)
       * @public
       */
      DataAdapterModbusFunction[DataAdapterModbusFunction["WRITE_REGISTERS_MULTIPLE"] = 16] = "WRITE_REGISTERS_MULTIPLE";
    })(exports.DataAdapterModbusFunction || (exports.DataAdapterModbusFunction = {}));
    /**
     * The order that color information is to be sent to the LEDs
     * @public
     */
    exports.LEDArrayColorOrder = void 0;
    (function (LEDArrayColorOrder) {
      /**
       * Byte order RGB (WS2811)
       * @public
       */
      LEDArrayColorOrder[LEDArrayColorOrder["RGB"] = 1] = "RGB";
      /**
       * Byte order GRB (WS2812B, SK6812)
       * @public
       */
      LEDArrayColorOrder[LEDArrayColorOrder["GRB"] = 2] = "GRB";
      /**
       * Byte order RGBW
       * @public
       */
      LEDArrayColorOrder[LEDArrayColorOrder["RGBW"] = 3] = "RGBW";
      /**
       * Byte order GRBW (SK6812RGBW)
       * @public
       */
      LEDArrayColorOrder[LEDArrayColorOrder["GRBW"] = 4] = "GRBW";
    })(exports.LEDArrayColorOrder || (exports.LEDArrayColorOrder = {}));
    /**
     * The animation type
     * @public
     */
    exports.LEDArrayAnimationType = void 0;
    (function (LEDArrayAnimationType) {
      /**
       * Move the pattern in a positively incrementing direction
       * @public
       */
      LEDArrayAnimationType[LEDArrayAnimationType["FORWARD_SCROLL"] = 1] = "FORWARD_SCROLL";
      /**
       * Move the pattern in a decrementing direction
       * @public
       */
      LEDArrayAnimationType[LEDArrayAnimationType["REVERSE_SCROLL"] = 2] = "REVERSE_SCROLL";
      /**
       * Fades LEDs between colors in the supplied pattern, chosen at random.
       * @public
       */
      LEDArrayAnimationType[LEDArrayAnimationType["RANDOMIZE"] = 3] = "RANDOMIZE";
      /**
       * Flip the pattern and move it in a positively incrementing direction, starting from the animation end point
       * @public
       */
      LEDArrayAnimationType[LEDArrayAnimationType["FORWARD_SCROLL_MIRROR"] = 4] = "FORWARD_SCROLL_MIRROR";
      /**
       * Flip the pattern and move it in a decrementing direction, starting from the animation end point
       * @public
       */
      LEDArrayAnimationType[LEDArrayAnimationType["REVERSE_SCROLL_MIRROR"] = 5] = "REVERSE_SCROLL_MIRROR";
    })(exports.LEDArrayAnimationType || (exports.LEDArrayAnimationType = {}));
    /**
     * The measurement range of the sound sensor
     * @public
     */
    exports.SPLRange = void 0;
    (function (SPLRange) {
      /**
       * Range 102dB
       * @public
       */
      SPLRange[SPLRange["DB_102"] = 1] = "DB_102";
      /**
       * Range 82dB
       * @public
       */
      SPLRange[SPLRange["DB_82"] = 2] = "DB_82";
    })(exports.SPLRange || (exports.SPLRange = {}));
    /**
     * The mode of the VINT port
     * @public
     */
    exports.HubPortMode = void 0;
    (function (HubPortMode) {
      /**
       * Communicate with a smart VINT device
       * @public
       */
      HubPortMode[HubPortMode["VINT"] = 0] = "VINT";
      /**
       * 5V Logic-level digital input
       * @public
       */
      HubPortMode[HubPortMode["DIGITAL_INPUT"] = 1] = "DIGITAL_INPUT";
      /**
       * 3.3V digital output
       * @public
       */
      HubPortMode[HubPortMode["DIGITAL_OUTPUT"] = 2] = "DIGITAL_OUTPUT";
      /**
       * 0-5V voltage input for non-ratiometric sensors
       * @public
       */
      HubPortMode[HubPortMode["VOLTAGE_INPUT"] = 3] = "VOLTAGE_INPUT";
      /**
       * 0-5V voltage input for ratiometric sensors
       * @public
       */
      HubPortMode[HubPortMode["VOLTAGE_RATIO_INPUT"] = 4] = "VOLTAGE_RATIO_INPUT";
    })(exports.HubPortMode || (exports.HubPortMode = {}));

    /** @internal */
    const PhidgetErrorDescription = {
      0: 'Success',
      1: 'Not Permitted',
      2: 'No Such Entity',
      3: 'Timed Out',
      58: 'Keep Alive Failure',
      4: 'Op Interrupted',
      5: 'IO Issue',
      6: 'Memory Issue',
      7: 'Access (Permission) Issue',
      8: 'Address Issue',
      9: 'Resource Busy',
      10: 'Object Exists',
      11: 'Object is not a directory',
      12: 'Object is a directory',
      13: 'Invalid',
      14: 'Too many open files in system',
      15: 'Too many open files',
      16: 'Not enough space',
      17: 'File too Big',
      18: 'Read Only Filesystem',
      19: 'Read Only Object',
      20: 'Operation Not Supported',
      21: 'Invalid Argument',
      22: 'Try again',
      26: 'Not Empty',
      28: 'Unexpected Error',
      27: 'Duplicate',
      37: 'Bad Credential',
      45: 'Network Unavailable',
      35: 'Connection Refused',
      46: 'Connection Reset',
      48: 'No route to host',
      40: 'No Such Device',
      50: 'Wrong Device',
      41: 'Broken Pipe',
      44: 'Name Resolution Failure',
      51: 'Unknown or Invalid Value',
      52: 'Device not Attached',
      53: 'Invalid or Unexpected Packet',
      54: 'Argument List Too Long',
      55: 'Bad Version',
      56: 'Closed',
      57: 'Not Configured',
      31: 'End of File',
      59: 'Failsafe Triggered',
      60: 'Invalid Value - Too High',
      61: 'Invalid Value - Too Low',
      62: 'Bad Power Supply',
      63: 'Power Cycle Required',
      64: 'Hall Sensor Error',
      65: 'Bad Current Readings',
      66: 'Bad Connection',
      67: 'NACK',
      68: 'Rejected'
    };

    /** @public */
    class PhidgetError extends Error {
      errorCode;
      innerException;
      constructor(code, message, innerException) {
        let msg = message || PhidgetErrorDescription[code];
        if (innerException != undefined) {
          let innerMsg;
          if (innerException instanceof Error) {
            innerMsg = innerException.message;
          } else if (typeof innerException === 'string') {
            innerMsg = innerException;
          } else {
            innerMsg = _JSON$stringify(innerException);
          }
          if (innerMsg.length > 0) msg += ' - ' + innerMsg;
        }
        super(msg);
        if (innerException instanceof Error) this.innerException = innerException;
        if (Error.captureStackTrace) Error.captureStackTrace(this, PhidgetError);
        this.name = "PhidgetError";
        this.errorCode = code;
      }
      get stacks() {
        let _stacks = this.stack;
        if (this.innerException && this.innerException.stack) _stacks += '\n<- ' + this.innerException.stack;
        return _stacks;
      }
    }

    let loglevel = exports.LogLevel.WARNING;
    let logsEnabled = true;
    /**
     * The Logging API controls logs sent to the console. By default, warnings and errors are printed.
     * Verbosity of logs can be changed, or logging can be disabled entirely.
     * @public
     */
    class Log {
      static setLevel(level) {
        loglevel = level;
      }
      static getLevel() {
        return loglevel;
      }
      /**
       * Enables logging within the Phidget library. Logs are sent to the console.
       * @param level - The logging level
       */
      static enable(level) {
        if (level !== undefined) loglevel = level;
        logsEnabled = true;
      }
      static disable() {
        logsEnabled = false;
      }
      /**
       * Writes a message to the Phidget library log.
       * @param level - The logging level
       * @param message - The message
       */
      static log(level, message) {
        switch (level) {
          case exports.LogLevel.CRITICAL:
            logcrit(message);
            break;
          case exports.LogLevel.ERROR:
            logerr(message);
            break;
          case exports.LogLevel.WARNING:
            logwarn(message);
            break;
          case exports.LogLevel.INFO:
            loginfo(message);
            break;
          case exports.LogLevel.DEBUG:
            logdebug(message);
            break;
          case exports.LogLevel.VERBOSE:
            logverbose(message);
            break;
        }
      }
    }
    let prevTime = null;
    function colouredText(txt, colour) {
      return txt;
    }
    function log(logger, lvl, msg, obj) {
      if (!logsEnabled) return;
      let msDiffTxt = '';
      {
        const curr = Number(new Date());
        const ms = curr - (prevTime || curr);
        prevTime = curr;
        msDiffTxt = colouredText(' +' + ms + 'ms');
      }
      const m = ('') + ('') + msg + msDiffTxt;
      if (obj) logger(m + ' -', obj);else logger(m);
    }
    function logcrit(msg, obj) {
      if (loglevel >= exports.LogLevel.CRITICAL) log(console.error, ' <' + colouredText('CRIT') + '>', msg, obj);
    }
    function logerr(msg, obj) {
      if (loglevel >= exports.LogLevel.ERROR) log(console.error, '<' + colouredText('ERROR') + '>', msg, obj);
    }
    function logwarn(msg, obj) {
      if (loglevel >= exports.LogLevel.WARNING) log(console.warn, ' <' + colouredText('Warn') + '>', msg, obj);
    }
    function loginfo(msg, obj) {
      if (loglevel >= exports.LogLevel.INFO) log(console.log, ' <' + 'Info' + '>', msg, obj);
    }
    function logdebug(msg, obj) {
      if (loglevel >= exports.LogLevel.DEBUG) log(console.debug, '<' + colouredText('Debug') + '>', msg, obj);
    }
    function logverbose(msg, obj) {
      if (loglevel >= exports.LogLevel.VERBOSE) log(console.debug, ' <' + colouredText('Verb') + '>', msg, obj);
    }
    function logEventException(err) {
      logwarn("Unhandled exception in event handler", err);
    }

    /** @internal */
    class PhidgetLock {
      _locked;
      releaseEvents;
      constructor() {
        this._locked = false;
        this.releaseEvents = [];
      }
      onRelease(listener) {
        this.releaseEvents.push(listener);
      }
      removeReleaseListener(listener) {
        const idx = this.releaseEvents.indexOf(listener);
        if (idx > -1) this.releaseEvents.splice(idx, 1);
      }
      emitRelease() {
        const listeners = this.releaseEvents.slice();
        const length = listeners.length;
        for (let i = 0; i < length; i++) listeners[i]();
        logverbose('LOCK Released!');
      }
      acquire() {
        logverbose('LOCK Aquiring..');
        return new Promise(resolve => {
          if (!this._locked) {
            this._locked = true;
            return resolve();
          }
          const tryAcquire = () => {
            if (!this._locked) {
              this._locked = true;
              this.removeReleaseListener(tryAcquire);
              logverbose('LOCK Aquired!');
              return resolve();
            }
          };
          this.onRelease(tryAcquire);
        });
      }
      release() {
        this._locked = false;
        setTimeout(() => this.emitRelease());
      }
      get locked() {
        return this._locked;
      }
    }

    const C_LIBRARY_VERSION = "1.26";
    /**
     * The base Phidget22 library version for this release - corresponds to the C library version
     * @public
     */
    const LibraryVersion = "Phidget22 - Version " + C_LIBRARY_VERSION + " - Built August 21, 2026";
    /**
     * The JavaScript library version
     * @public
     */
    const JSLibraryVersion = "3.26.1 - August 21, 2026";
    const Managers = [];
    const Connections = [];
    const UserPhidgets = [];
    let Epoch;
    function tm() {
      if (Epoch == undefined) Epoch = Date.now();
      return Date.now() - Epoch;
    }
    async function scanChannels(userphid) {
      for (const conn of Connections) {
        if (userphid._isLocal && conn._isRemote) continue;
        if (userphid._isRemote && conn._isLocal) continue;
        if (await conn._match(userphid)) return true;
      }
      return false;
    }
    async function scanUserPhidgets(ch) {
      for (const userphid of UserPhidgets) {
        if (await ch.tryMatchOpen(userphid)) return;
      }
    }
    let scanningActive = false;
    let scanStopped;
    let scanLock;
    let scanTimeout;
    async function startScanningUserPhidgets() {
      if (!scanLock) scanLock = new PhidgetLock();
      await scanLock.acquire();
      if (scanningActive) {
        scanLock.release();
        return;
      }
      const scan = () => {
        scanTimeout = undefined;
        const again = () => {
          if (scanningActive) {
            scanTimeout = setTimeout(scan, 1000);
          } else {
            if (scanStopped) {
              scanStopped();
              scanStopped = undefined;
            }
          }
        };
        Promise.all(UserPhidgets.filter(userphid => !userphid._attaching && !userphid._isopen).map(userphid => {
          return scanChannels(userphid);
        })).then(() => {
          again();
        }).catch(err => {
          logerr("Error during User Phidgets scan", err);
          again();
        });
      };
      scanningActive = true;
      loginfo("Starting User Phidget scanning");
      scan();
      scanLock.release();
    }
    async function stopScanningUserPhidgets() {
      if (!scanLock) scanLock = new PhidgetLock();
      await scanLock.acquire();
      if (!scanningActive) {
        scanLock.release();
        return;
      }
      scanningActive = false;
      if (scanTimeout != undefined) {
        clearTimeout(scanTimeout);
      } else {
        const scanStopPromise = new Promise(resolve => {
          scanStopped = resolve;
        });
        await scanStopPromise;
      }
      loginfo("User Phidget scanning Stopped");
      scanLock.release();
    }
    function managerDeviceAttach(dev) {
      for (const m of Managers) m._deviceAttach(dev);
    }
    function managerDeviceDetach(dev) {
      for (const m of Managers) m._deviceDetach(dev);
    }
    function managerChannelAttach(ch) {
      for (const m of Managers) m._channelAttach(ch);
    }
    function managerChannelDetach(ch) {
      for (const m of Managers) m._channelDetach(ch);
    }

    let _onConnectionRemoved = null;
    let _onConnectionAdded = null;
    function onConnectionRemoved(conn) {
      if (_onConnectionRemoved) _onConnectionRemoved(conn);
    }
    function onConnectionAdded(conn) {
      if (_onConnectionAdded) _onConnectionAdded(conn);
    }
    let ConnectionID = 0;
    /** @public */
    class PhidgetConnection {
      /** @internal */
      _channels;
      /** @internal */
      _devices;
      /** @internal */
      _id;
      connected;
      name;
      onError = null;
      static setOnConnectionRemoved(func) {
        _onConnectionRemoved = func;
      }
      static setOnConnectionAdded(func) {
        _onConnectionAdded = func;
      }
      /** @internal */
      constructor(opts) {
        if (opts != undefined && typeof opts !== 'object') throw new Error('Options argument must be an object');
        this._id = ConnectionID++;
        this.connected = false;
        this._channels = new Map();
        this._devices = new Map();
        this.name = '';
        if (opts != undefined) {
          if (opts.name != undefined && typeof opts.name === 'string') this.name = opts.name;
          if (opts.onError != undefined && typeof opts.onError === 'function') this.onError = opts.onError;
        }
        if (this.onError === undefined) {
          this.onError = function (code, msg) {
            logerr("Connection error: " + msg + ':0x' + code.toString(16));
          };
        }
        Connections.push(this);
        onConnectionAdded(this);
      }
      delete() {
        if (this.connected) throw new PhidgetError(exports.ErrorCode.BUSY, 'close connection before deleting');
        onConnectionRemoved(this);
        if (_includesInstanceProperty(Connections).call(Connections, this)) Connections.splice(Connections.indexOf(this), 1);
      }
      getKey() {
        return this._id;
      }
      get key() {
        return this._id;
      }
      /** @internal */
      get _isLocal() {
        return this._type === 0;
      }
      /** @internal */
      get _isRemote() {
        return this._type === 1;
      }
      /** @internal */
      _getChannel(id) {
        const ch = this._channels.get(id);
        if (ch == undefined) throw new PhidgetError(exports.ErrorCode.UNEXPECTED, 'invalid channel id:' + id);
        return ch;
      }
      /** @internal */
      _getDevice(id) {
        const dev = this._devices.get(id);
        if (dev == undefined) return null;
        return dev;
      }
      /** @internal */
      _detachAllDevices() {
        while (this._devices.size > 0) {
          const last = Array.from(this._devices.values())[this._devices.size - 1];
          try {
            this._deviceDetach(last);
          } catch (err) {
            logerr("Error while detaching all devices", err);
          }
        }
      }
      /** @internal */
      _deviceAttach(dev) {
        if (this._devices.has(dev.id)) throw new PhidgetError(exports.ErrorCode.DUPLICATE, 'duplicate device:' + dev);
        (dev.isHubPort ? logverbose : loginfo)("Device Attach: " + dev);
        this._devices.set(dev.id, dev);
        managerDeviceAttach(dev);
      }
      /** @internal */
      _deviceDetach(dev) {
        if (!this._devices.has(dev.id)) throw new PhidgetError(exports.ErrorCode.NO_SUCH_ENTITY, 'no such device:' + dev);
        for (const ch of this._channels.entries()) {
          if (ch[1].parent === dev) {
            logverbose("Channel Detach: " + ch[1]);
            managerChannelDetach(ch[1]);
            ch[1].detach();
            this._channels.delete(ch[0]);
          }
        }
        (dev.isHubPort ? logverbose : loginfo)("Device Detach: " + dev);
        managerDeviceDetach(dev);
        this._devices.delete(dev.id);
      }
      /** @internal */
      _channelAttach(ch) {
        if (this._channels.has(ch.id)) throw new PhidgetError(exports.ErrorCode.DUPLICATE, 'duplicate channel:' + ch);
        logverbose("Channel Attach: " + ch);
        this._channels.set(ch.id, ch);
        managerChannelAttach(ch);
        scanUserPhidgets(ch).catch(err => {
          logerr("Error scanning user phidgets", err);
        });
      }
      /** @internal */
      async _match(userphid) {
        for (const ch of this._channels.values()) {
          if (await ch.tryMatchOpen(userphid)) return true;
        }
        return false;
      }
    }

    /** @internal */
    class Request {
      hdrlen;
      flgs;
      len;
      reqseq;
      repseq;
      type;
      stype;
      constructor(dataOrLength, flgs, reqseq, repseq, type, stype) {
        if (typeof dataOrLength === 'number') {
          if (flgs === undefined || reqseq === undefined || repseq === undefined || type === undefined || stype === undefined) throw new Error("Invalid Input");
          this.len = dataOrLength;
          this.flgs = flgs;
          this.reqseq = reqseq;
          this.repseq = repseq;
          this.type = type;
          this.stype = stype;
          this.hdrlen = 16;
        } else {
          this.hdrlen = this.parse(dataOrLength);
        }
      }
      toString() {
        return '{flags:0x' + this.flgs.toString(16) + ' len:' + this.len + ' reqseq:' + this.reqseq + ' repseq:' + this.repseq + ' type:' + this.type + ' subtype:' + this.stype + '}';
      }
      parse(buf) {
        const magic = buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0];
        this.len = buf[7] << 24 | buf[6] << 16 | buf[5] << 8 | buf[4];
        this.flgs = buf[9] << 8 | buf[8];
        this.reqseq = buf[11] << 8 | buf[10];
        this.repseq = buf[13] << 8 | buf[12];
        this.type = buf[14];
        this.stype = buf[15];
        if (magic != 1346914608) throw new Error("Bad Request Magic");
        return 16;
      }
      get buffer() {
        const array = new Uint8Array(16);
        array[3] = 1346914608 >> 24 & 0xff;
        array[2] = 1346914608 >> 16 & 0xff;
        array[1] = 1346914608 >> 8 & 0xff;
        array[0] = 1346914608 & 0xff;
        array[7] = this.len >> 24 & 0xff;
        array[6] = this.len >> 16 & 0xff;
        array[5] = this.len >> 8 & 0xff;
        array[4] = this.len & 0xff;
        array[9] = this.flgs >> 8 & 0xff;
        array[8] = this.flgs & 0xff;
        array[11] = this.reqseq >> 8 & 0xff;
        array[10] = this.reqseq & 0xff;
        array[13] = this.repseq >> 8 & 0xff;
        array[12] = this.repseq & 0xff;
        array[14] = this.type;
        array[15] = this.stype;
        return array;
      }
    }

    var regexpFlagsDetection;
    var hasRequiredRegexpFlagsDetection;
    function requireRegexpFlagsDetection () {
    	if (hasRequiredRegexpFlagsDetection) return regexpFlagsDetection;
    	hasRequiredRegexpFlagsDetection = 1;
    	var globalThis =  requireGlobalThis();
    	var fails =  requireFails();
    	var RegExp = globalThis.RegExp;
    	var FLAGS_GETTER_IS_CORRECT = !fails(function () {
    	  var INDICES_SUPPORT = true;
    	  try {
    	    RegExp('.', 'd');
    	  } catch (error) {
    	    INDICES_SUPPORT = false;
    	  }
    	  var O = {};
    	  var calls = '';
    	  var expected = INDICES_SUPPORT ? 'dgimsy' : 'gimsy';
    	  var addGetter = function (key, chr) {
    	    Object.defineProperty(O, key, { get: function () {
    	      calls += chr;
    	      return true;
    	    } });
    	  };
    	  var pairs = {
    	    dotAll: 's',
    	    global: 'g',
    	    ignoreCase: 'i',
    	    multiline: 'm',
    	    sticky: 'y'
    	  };
    	  if (INDICES_SUPPORT) pairs.hasIndices = 'd';
    	  for (var key in pairs) addGetter(key, pairs[key]);
    	  var result = Object.getOwnPropertyDescriptor(RegExp.prototype, 'flags').get.call(O);
    	  return result !== expected || calls !== expected;
    	});
    	regexpFlagsDetection = { correct: FLAGS_GETTER_IS_CORRECT };
    	return regexpFlagsDetection;
    }

    var regexpFlags;
    var hasRequiredRegexpFlags;
    function requireRegexpFlags () {
    	if (hasRequiredRegexpFlags) return regexpFlags;
    	hasRequiredRegexpFlags = 1;
    	var anObject =  requireAnObject();
    	regexpFlags = function () {
    	  var that = anObject(this);
    	  var result = '';
    	  if (that.hasIndices) result += 'd';
    	  if (that.global) result += 'g';
    	  if (that.ignoreCase) result += 'i';
    	  if (that.multiline) result += 'm';
    	  if (that.dotAll) result += 's';
    	  if (that.unicode) result += 'u';
    	  if (that.unicodeSets) result += 'v';
    	  if (that.sticky) result += 'y';
    	  return result;
    	};
    	return regexpFlags;
    }

    var regexpGetFlags;
    var hasRequiredRegexpGetFlags;
    function requireRegexpGetFlags () {
    	if (hasRequiredRegexpGetFlags) return regexpGetFlags;
    	hasRequiredRegexpGetFlags = 1;
    	var call =  requireFunctionCall();
    	var hasOwn =  requireHasOwnProperty();
    	var isPrototypeOf =  requireObjectIsPrototypeOf();
    	var regExpFlagsDetection =  requireRegexpFlagsDetection();
    	var regExpFlagsGetterImplementation =  requireRegexpFlags();
    	var RegExpPrototype = RegExp.prototype;
    	regexpGetFlags = regExpFlagsDetection.correct ? function (it) {
    	  return it.flags;
    	} : function (it) {
    	  return (!regExpFlagsDetection.correct && isPrototypeOf(RegExpPrototype, it) && !hasOwn(it, 'flags'))
    	    ? call(regExpFlagsGetterImplementation, it)
    	    : it.flags;
    	};
    	return regexpGetFlags;
    }

    var flags$1;
    var hasRequiredFlags$2;
    function requireFlags$2 () {
    	if (hasRequiredFlags$2) return flags$1;
    	hasRequiredFlags$2 = 1;
    	var getRegExpFlags =  requireRegexpGetFlags();
    	flags$1 = getRegExpFlags;
    	return flags$1;
    }

    var flags_1;
    var hasRequiredFlags$1;
    function requireFlags$1 () {
    	if (hasRequiredFlags$1) return flags_1;
    	hasRequiredFlags$1 = 1;
    	var isPrototypeOf =  requireObjectIsPrototypeOf();
    	var flags =  requireFlags$2();
    	var RegExpPrototype = RegExp.prototype;
    	flags_1 = function (it) {
    	  return (it === RegExpPrototype || isPrototypeOf(RegExpPrototype, it)) ? flags(it) : it.flags;
    	};
    	return flags_1;
    }

    var flags;
    var hasRequiredFlags;
    function requireFlags () {
    	if (hasRequiredFlags) return flags;
    	hasRequiredFlags = 1;
    	var parent =  requireFlags$1();
    	flags = parent;
    	return flags;
    }

    var flagsExports = /*@__PURE__*/ requireFlags();
    var _flagsInstanceProperty = /*@__PURE__*/getDefaultExportFromCjs(flagsExports);

    /** @internal */
    const BPE_ISEVENT_FLAG = 0x01;
    /** @internal */
    class BridgePacket {
      version;
      source;
      flags;
      vpkt;
      ch;
      entryCount;
      entries;
      local;
      constructor(conn, data) {
        if (conn != undefined && data != undefined) {
          this.version = data.v;
          this.source = data.s;
          this.flags = data.f;
          this.vpkt = data.p;
          this.ch = conn._getChannel(data.O);
          this.entryCount = data.c;
          this.entries = this.toStoredEntries(data.e);
          this.local = false;
        } else {
          this.version = 0;
          this.source = 2;
          this.flags = 0;
          this.entryCount = 0;
          this.entries = {};
          this.local = true;
        }
      }
      toStoredEntries(entries) {
        const storedEntries = {};
        for (const key in entries) {
          const entry = entries[key];
          if (entry.t === 'R') {
            storedEntries[key] = {
              t: entry.t,
              v: new Uint8Array(entry.v)
            };
          } else {
            storedEntries[key] = entry;
          }
        }
        return storedEntries;
      }
      toJsonEntries(entries) {
        const jsonEntries = {};
        for (const key in entries) {
          const entry = entries[key];
          if (entry.v instanceof Uint8Array) {
            jsonEntries[key] = {
              t: entry.t,
              v: Array.from(entry.v)
            };
          } else {
            jsonEntries[key] = entry;
          }
        }
        return jsonEntries;
      }
      isEvent() {
        if (_flagsInstanceProperty(this) & BPE_ISEVENT_FLAG) return true;
        return false;
      }
      entryType(type) {
        switch (type) {
          case 'c':
          case 'h':
          case 'uh':
          case 'd':
          case 'u':
          case 'l':
          case 'ul':
            return 1;
          case 'f':
          case 'g':
            return 2;
          case 's':
            return 3;
          case 'R':
            return 6;
          case 'I':
          case 'G':
          case 'U':
          case 'H':
            return 4;
          case 'J':
            return 5;
          default:
            return -1;
        }
      }
      validate(e) {
        switch (this.entryType(e.type)) {
          case 1:
            if (typeof e.value !== 'number') {
              const num = Number(e.value);
              if (Number.isNaN(num)) throw new TypeError('Expected number but got ' + typeof e.value);
              e.value = num;
            }
            e.value = Math.round(e.value);
            return;
          case 2:
            if (typeof e.value !== 'number') {
              const num = Number(e.value);
              if (Number.isNaN(num)) throw new TypeError('Expected number but got ' + typeof e.value);
              e.value = num;
            }
            return;
          case 3:
            if (typeof e.value == 'string') return;
            throw new TypeError('Expected string but got ' + typeof e.value);
          case 5:
            if (typeof e.value === 'object') return;
            throw new TypeError('Expected object but got ' + typeof e.value);
          case 4:
            if (Array.isArray(e.value)) return;
            throw new TypeError('Expected an Array but got ' + typeof e.value);
          case 6:
            if (e.value instanceof Uint8Array) return;
            throw new TypeError('Expected Uint8Array but got ' + typeof e.value);
          default:
            throw new Error('Invalid entry type: ' + e.type);
        }
      }
      set(val) {
        this.validate(val);
        if (val.name in this.entries) throw new Error('value [' + val.name + '] already set');
        const e = {
          t: val.type,
          v: val.value
        };
        this.entries[val.name] = e;
        this.entryCount++;
      }
      remove(name) {
        const entry = {
          t: name};
        if (!(entry.t in this.entries)) return;
        const filteredEntries = {};
        for (const e in this.entries) {
          if (e !== entry.t) {
            filteredEntries[e] = this.entries[e];
          }
        }
        this.entries = filteredEntries;
        this.entryCount--;
      }
      add(val) {
        val.name = this.entryCount.toString();
        this.set(val);
      }
      getJsonOut(ch) {
        if (this.vpkt == undefined) throw new Error('vpkt not set!');
        const bp = {
          v: this.version,
          s: this.source,
          f: _flagsInstanceProperty(this),
          p: this.vpkt,
          I: ch.parent.id,
          X: ch.uniqueIndex,
          c: this.entryCount,
          e: this.toJsonEntries(this.entries)
        };
        return bp;
      }
      async send(ch, vpkt, callBridgeInput = true) {
        if (!ch || !ch.isopen) throw new PhidgetError(exports.ErrorCode.NOT_ATTACHED);
        this.vpkt = vpkt;
        const response = await ch.send(this);
        if (callBridgeInput) ch.bridgeInput(this);
        return response;
      }
      deliver() {
        if (!this.ch) throw new PhidgetError(exports.ErrorCode.UNEXPECTED, 'Bridge packet missing channel');
        if (this.ch.isopen === false) return;
        this.ch.bridgeInput(this);
      }
      sendToChannel(ch, vpkt) {
        this.vpkt = vpkt;
        ch.clearErrorEvent();
        ch.bridgeInput(this);
      }
      getNumber(name) {
        if (!(name in this.entries)) throw new Error(`BP entry '${name}' does not exist.`);
        const type = this.entryType(this.entries[name].t);
        if (type != 2 && type != 1) throw new Error(`BP entry '${name}' is not a number.`);
        if (typeof this.entries[name].v !== 'number') throw new Error(`BP entry '${name}' has an unexpected value!`);
        return this.entries[name].v;
      }
      getArray(name) {
        if (!(name in this.entries)) throw new Error(`BP entry '${name}' does not exist.`);
        const type = this.entryType(this.entries[name].t);
        if (type != 4) throw new Error(`BP entry '${name}' is not an array.`);
        if (!Array.isArray(this.entries[name].v)) throw new Error(`BP entry '${name}' has an unexpected value!`);
        return this.entries[name].v;
      }
      getByteArray(name) {
        if (!(name in this.entries)) throw new Error(`BP entry '${name}' does not exist.`);
        const type = this.entryType(this.entries[name].t);
        if (type != 6) throw new Error(`BP entry '${name}' is not a byte array.`);
        if (!(this.entries[name].v instanceof Uint8Array)) throw new Error(`BP entry '${name}' has an unexpected value!`);
        return this.entries[name].v;
      }
      getObject(name) {
        if (!(name in this.entries)) throw new Error(`BP entry '${name}' does not exist.`);
        const type = this.entryType(this.entries[name].t);
        if (type != 5) throw new Error(`BP entry '${name}' is not an object.`);
        if (typeof this.entries[name].v !== 'object') throw new Error(`BP entry '${name}' has an unexpected value!`);
        return this.entries[name].v;
      }
      getString(name) {
        if (!(name in this.entries)) throw new Error(`BP entry '${name}' does not exist.`);
        const type = this.entryType(this.entries[name].t);
        if (type != 3) throw new Error(`BP entry '${name}' is not a string.`);
        if (this.entries[name].v === null) throw new Error(`BP entry '${name}' is null.`);
        if (typeof this.entries[name].v !== 'string') throw new Error(`BP entry '${name}' has an unexpected value!`);
        return this.entries[name].v;
      }
      getBoolean(name) {
        if (!(name in this.entries)) throw new Error(`BP entry '${name}' does not exist.`);
        const type = this.entryType(this.entries[name].t);
        if (type != 1) throw new Error(`BP entry '${name}' is not a boolean.`);
        if (typeof this.entries[name].v !== 'number') throw new Error(`BP entry '${name}' has an unexpected value!`);
        if (this.entries[name].v === 0) return false;
        if (this.entries[name].v === 1) return true;
        if (this.entries[name].v === 2) return 2;
        throw new Error(`BP entry '${name}' has an unexpected value!`);
      }
    }

    /** @internal */
    const ChannelClassName = {
      0: 'PhidgetNone',
      1: 'PhidgetAccelerometer',
      35: 'PhidgetBLDCMotor',
      14: 'PhidgetCapacitiveTouch',
      2: 'PhidgetCurrentInput',
      38: 'PhidgetCurrentOutput',
      3: 'PhidgetDataAdapter',
      4: 'PhidgetDCMotor',
      36: 'PhidgetDictionary',
      5: 'PhidgetDigitalInput',
      6: 'PhidgetDigitalOutput',
      7: 'PhidgetDistanceSensor',
      8: 'PhidgetEncoder',
      32: 'PhidgetFirmwareUpgrade',
      9: 'PhidgetFrequencyCounter',
      33: 'PhidgetGeneric',
      10: 'PhidgetGPS',
      12: 'PhidgetGyroscope',
      13: 'PhidgetHub',
      15: 'PhidgetHumiditySensor',
      16: 'PhidgetIR',
      11: 'PhidgetLCD',
      19: 'PhidgetLEDArray',
      17: 'PhidgetLightSensor',
      18: 'PhidgetMagnetometer',
      34: 'PhidgetMotorPositionController',
      39: 'PhidgetMotorVelocityController',
      37: 'PhidgetPHSensor',
      20: 'PhidgetPowerGuard',
      21: 'PhidgetPressureSensor',
      22: 'PhidgetRCServo',
      23: 'PhidgetResistanceInput',
      24: 'PhidgetRFID',
      25: 'PhidgetSoundSensor',
      26: 'PhidgetSpatial',
      27: 'PhidgetStepper',
      28: 'PhidgetTemperatureSensor',
      29: 'PhidgetVoltageInput',
      30: 'PhidgetVoltageOutput',
      31: 'PhidgetVoltageRatioInput'
    };

    /** @internal */
    const DeviceClassName = {
      0: 'PhidgetNone',
      1: 'PhidgetAccelerometer',
      2: 'PhidgetAdvancedServo',
      3: 'PhidgetAnalog',
      4: 'PhidgetBridge',
      28: 'PhidgetCurrentInput',
      26: 'PhidgetCurrentOutput',
      25: 'PhidgetDataAdapter',
      24: 'PhidgetDictionary',
      5: 'PhidgetEncoder',
      23: 'PhidgetFirmwareUpgrade',
      6: 'PhidgetFrequencyCounter',
      27: 'PhidgetFrequencyOutput',
      22: 'PhidgetGeneric',
      7: 'PhidgetGPS',
      8: 'PhidgetHub',
      9: 'PhidgetInterfaceKit',
      10: 'PhidgetIR',
      11: 'PhidgetLED',
      12: 'PhidgetLEDArray',
      13: 'PhidgetMotorControl',
      14: 'PhidgetPHSensor',
      15: 'PhidgetRFID',
      16: 'PhidgetServo',
      17: 'PhidgetSpatial',
      18: 'PhidgetStepper',
      19: 'PhidgetTemperatureSensor',
      20: 'PhidgetTextLCD',
      21: 'PhidgetVINT',
      29: 'PhidgetVoltageInput'
    };

    /**
     * The core Phidget class deals with functionality common to all Phidgets, such as opening and closing them, or setting Attach, Detach, Error event handlers.
     *
     * This class is also used to specify the associations between the Phidget software objects and their corresponding physical devices, and makes it possible to determine which Phidget is which in cases where it might otherwise be ambiguous.
     *
     * This class contains various functions such as **Release**, **Retain**, and **getParent** designed to be used with the **Phidget Manager**. These specialized functions may be safely ignored if your application does not require a **Manager**. You can check the **Manager API** for more information.
     * @public
     */
    class PhidgetBase {
      static get ANY_SERIAL_NUMBER() {
        return -1;
      }
      static get ANY_HUB_PORT() {
        return -1;
      }
      static get ANY_CHANNEL() {
        return -1;
      }
      static get ANY_LABEL() {
        return null;
      }
      static get INFINITE_TIMEOUT() {
        return 0;
      }
      static get DEFAULT_TIMEOUT() {
        return 2500;
      }
      static get AUTO_HUBPORTSPEED() {
        return 0;
      }
      /**
       * Gets the attached status of channel. A Phidget is attached after it has been opened and the Phidget library finds and connects to the corresponding hardware device.
       *
       * *   Most API calls are only valid on attached Phidgets.
       * @throws `PhidgetError`
       */
      get attached() {
        return this.getAttached();
      }
      /**
       * get: Gets the channel index of the channel on the device.
       *
       * set: Specifies the channel index to be opened. The default channel is 0. Set to `ANY_CHANNEL` to open any channel on the specified device.
       *
       * If setting this property, it must be set before the channel is opened. The behaviour of setting this property while the channel is open is undefined.
       * @throws `PhidgetError`
       */
      get channel() {
        return this.getChannel();
      }
      set channel(channel) {
        this.setChannel(channel);
      }
      /**
       * Returns true if this represents a channel, false if this represents a device. Mostly for use alongside `getParent()` to distinguish channel handles from device handles.
       * @throws `PhidgetError`
       */
      get isChannel() {
        return this.getIsChannel();
      }
      /**
       * Gets the channel class of the channel.
       * @throws `PhidgetError`
       */
      get channelClass() {
        return this.getChannelClass();
      }
      /**
       * Gets the name of the channel class the channel belongs to.
       * @throws `PhidgetError`
       */
      get channelClassName() {
        return this.getChannelClassName();
      }
      /**
       * Gets the channel's name. This name serves as a description of the specific nature of the channel.
       * @throws `PhidgetError`
       */
      get channelName() {
        return this.getChannelName();
      }
      /**
       * Controls whether the state of this channel persists across attach and close. By default, channels are reset on attach and close. Note that any defaults listed in the API must be set by the user when Persistence is enabled.
       * @throws `PhidgetError`
       */
      get channelPersistence() {
        return this.getChannelPersistence();
      }
      /**
       * Gets the subclass for this channel. Allows for identifying channels with specific characteristics without needing to know the exact device and channel index.
       * @throws `PhidgetError`
       */
      get channelSubclass() {
        return this.getChannelSubclass();
      }
      /**
       * Gets the connection associated with this Phidget.
       * @throws `PhidgetError`
       */
      get connection() {
        return this.getConnection();
      }
      /**
       * Gets the device class for the Phidget which this channel is a part of.
       * @throws `PhidgetError`
       */
      get deviceClass() {
        return this.getDeviceClass();
      }
      /**
       * Gets the name of the device class for the Phidget which this channel is a part of.
       * @throws `PhidgetError`
       */
      get deviceClassName() {
        return this.getDeviceClassName();
      }
      /**
       * Gets the string which will match the filename of the firmware upgrade file
       * @throws `PhidgetError`
       * @internal
       */
      get deviceFirmwareUpgradeString() {
        return this.getDeviceFirmwareUpgradeString();
      }
      /**
       * Gets the Device ID for the Phidget which this channel is a part of.
       * @throws `PhidgetError`
       */
      get deviceID() {
        return this.getDeviceID();
      }
      /**
       * get: Gets the label of the Phidget which this channel is a part of. A device label is a custom string used to more easily identify a Phidget. Labels are written to a Phidget using `writeDeviceLabel()`, or by right-clicking the device and setting a label in the Phidget Control Panel for Windows.
       *
       * set: Specifies the label of the Phidget to be opened. Leave un-set to open any label. A device label is a custom string used to more easily identify a Phidget. Labels are written to a Phidget using `writeDeviceLabel()`, or by right-clicking the device and setting a label in the Phidget Control Panel for Windows.
       *
       * If setting this property, it must be set before the channel is opened. The behaviour of setting this property while the channel is open is undefined.
       * @throws `PhidgetError`
       */
      get deviceLabel() {
        return this.getDeviceLabel();
      }
      set deviceLabel(deviceLabel) {
        this.setDeviceLabel(deviceLabel);
      }
      /**
       * Gets the name of the Phidget which this channel is a part of.
       * @throws `PhidgetError`
       */
      get deviceName() {
        return this.getDeviceName();
      }
      /**
       * get: Gets the serial number of the Phidget which this channel is a part of.
       * If the channel is part of a VINT device, this will be the serial number of the VINT Hub the device is attached to.
       *
       * set: Specifies the serial number of the Phidget to be opened. Leave un-set, or set to `ANY_SERIAL_NUMBER` to open any serial number.
       * If the channel is part of a VINT device, this will be the serial number of the VINT Hub the device is attached to.
       *
       * If setting this property, it must be set before the channel is opened. The behaviour of setting this property while the channel is open is undefined.
       * @throws `PhidgetError`
       */
      get deviceSerialNumber() {
        return this.getDeviceSerialNumber();
      }
      set deviceSerialNumber(deviceSerialNumber) {
        this.setDeviceSerialNumber(deviceSerialNumber);
      }
      /**
       * Gets the SKU of the Phidget which this channel is a part of. If there are multiple possible SKUs, they will be separated by a /.
       * @throws `PhidgetError`
       */
      get deviceSKU() {
        return this.getDeviceSKU();
      }
      /**
       * Gets the firmware version of the Phidget which this channel is a part of.
       * @throws `PhidgetError`
       */
      get deviceVersion() {
        return this.getDeviceVersion();
      }
      /**
       * Gets the vint id for the Phidget which this channel is a part of.
       * @throws `PhidgetError`
       * @internal
       */
      get deviceVINTID() {
        return this.getDeviceVINTID();
      }
      /**
       * Gets the hub that this channel is attached to.
       * @throws `PhidgetError`
       */
      get hub() {
        return this.getHub();
      }
      /**
       * get: Gets the hub port index of the VINT Hub port that the channel is attached to.
       *
       * set: Specifies the hub port index of the VINT Hub port to open this channel on. Leave un-set, or set to `ANY_HUB_PORT` to open the channel on any VINT Hub port
       *
       * If setting this property, it must be set before the channel is opened. The behaviour of setting this property while the channel is open is undefined.
       * @throws `PhidgetError`
       */
      get hubPort() {
        return this.getHubPort();
      }
      set hubPort(hubPort) {
        this.setHubPort(hubPort);
      }
      /**
       * Gets the number of VINT ports present on the VINT Hub that the channel is attached to.
       * @throws `PhidgetError`
       */
      get hubPortCount() {
        return this.getHubPortCount();
      }
      /**
       * get: Gets whether this channel is a VINT Hub port channel, or part of a VINT device attached to a hub port.
       *
       * set: Specifies whether this channel should be opened on a VINT Hub port directly, or on a VINT device attached to a hub port.
       *
       * If setting this property, it must be set before the channel is opened. The behaviour of setting this property while the channel is open is undefined.
       * @throws `PhidgetError`
       */
      get isHubPortDevice() {
        return this.getIsHubPortDevice();
      }
      set isHubPortDevice(isHubPortDevice) {
        this.setIsHubPortDevice(isHubPortDevice);
      }
      /**
       * Configures the communication speed for this VINT device. Both the `hubPortSupportsSetSpeed` and `VINTDeviceSupportsSetSpeed` must be true in order to set the hub port speed.Available speeds are: 100000, 160000, 250000, 400000, 500000, 800000 and 1000000. Setting any other speed will select the nearest lower supported speed. The upper speed is bound by the lesser of `maxHubPortSpeed` and `maxVINTDeviceSpeed`. Set the speed to `AUTO_HUBPORTSPEED` to enable Auto Set Speed on Hubs that support it (enabled by default).
       * @throws `PhidgetError`
       */
      get hubPortSpeed() {
        return this.getHubPortSpeed();
      }
      /**
       * The max communication speed of a high-speed capable VINT Port.
       * @throws `PhidgetError`
       */
      get maxHubPortSpeed() {
        return this.getMaxHubPortSpeed();
      }
      /**
       * Indicates that the communication speed of this VINT port can be set automatically.
       * @throws `PhidgetError`
       */
      get hubPortSupportsAutoSetSpeed() {
        return this.getHubPortSupportsAutoSetSpeed();
      }
      /**
       * Indicates that the communication speed of this VINT port can be set.
       * @throws `PhidgetError`
       */
      get hubPortSupportsSetSpeed() {
        return this.getHubPortSupportsSetSpeed();
      }
      /**
       * Gets a key which identifies this device or channel uniquely. This can be useful for correlating attach/detach events from the **Manager**.
       * @throws `PhidgetError`
       */
      get key() {
        return this.getKey();
      }
      /**
       * get: Returns true when this channel is attached directly on the local machine, or false otherwise.
       *
       * set: Set to True if the channel is to be opened locally, and not over a network. If both this and `isRemote` are set to False (the default), the channel will be opened either locally or remotely, on whichever matching channel is found first.
       *
       * If setting this property, it must be set before the channel is opened. The behaviour of setting this property while the channel is open is undefined.
       * @throws `PhidgetError`
       */
      get isLocal() {
        return this.getIsLocal();
      }
      set isLocal(isLocal) {
        this.setIsLocal(isLocal);
      }
      /**
       * Returns true if `open()` has been called on this channel.
       * @throws `PhidgetError`
       */
      get isOpen() {
        return this.getIsOpen();
      }
      /**
       * Gets the handle of the parent device of the given Phidget handle.
       *
       * For example, this would refer to the device the channel is a part of, or the Hub that a device is plugged into.
       *
       * This is useful when used alongside a **Phidget Manager** to create device trees like the one in the Phidget Control Panel.
       *
       * *   This can be used to travel up the device tree and get device information at each step.
       * *   The root device will return a null handle
       * *   Parent handles always refer to devices. See `getIsChannel()`
       * @throws `PhidgetError`
       */
      get parent() {
        return this.getParent();
      }
      /**
       * get: Returns true when this channel is attached via a Phidget network server, or false otherwise.
       *
       * set:
       *
       * Set to True if the channel is to be opened remotely, rather than locally. If both this and `isLocal` are set to False (the default), the channel will be opened either locally or remotely, on whichever matching channel is found first.
       *
       * If setting this property, it must be set before the channel is opened. The behaviour of setting this property while the channel is open is undefined.
       * @throws `PhidgetError`
       */
      get isRemote() {
        return this.getIsRemote();
      }
      set isRemote(isRemote) {
        this.setIsRemote(isRemote);
      }
      /**
       * The max communication speed of a high-speed capable VINT Device.
       * @throws `PhidgetError`
       */
      get maxVINTDeviceSpeed() {
        return this.getMaxVINTDeviceSpeed();
      }
      /**
       * Indicates that the communication speed of this VINT device can be set automatically.
       * @throws `PhidgetError`
       */
      get VINTDeviceSupportsAutoSetSpeed() {
        return this.getVINTDeviceSupportsAutoSetSpeed();
      }
      /**
       * Indicates that the communication speed of this VINT device can be set.
       * @throws `PhidgetError`
       */
      get VINTDeviceSupportsSetSpeed() {
        return this.getVINTDeviceSupportsSetSpeed();
      }
    }

    /** @internal */
    function AllowChannelPersistence(cls) {
      switch (cls) {
        case exports.ChannelClass.ACCELEROMETER:
          return false;
        case exports.ChannelClass.BLDC_MOTOR:
          return false;
        case exports.ChannelClass.CAPACITIVE_TOUCH:
          return false;
        case exports.ChannelClass.CURRENT_INPUT:
          return false;
        case exports.ChannelClass.DATA_ADAPTER:
          return true;
        case exports.ChannelClass.DC_MOTOR:
          return false;
        case exports.ChannelClass.DICTIONARY:
          return false;
        case exports.ChannelClass.DIGITAL_INPUT:
          return false;
        case exports.ChannelClass.DIGITAL_OUTPUT:
          return true;
        case exports.ChannelClass.DISTANCE_SENSOR:
          return false;
        case exports.ChannelClass.ENCODER:
          return false;
        case exports.ChannelClass.FIRMWARE_UPGRADE:
          return false;
        case exports.ChannelClass.FREQUENCY_COUNTER:
          return false;
        case exports.ChannelClass.GENERIC:
          return false;
        case exports.ChannelClass.GPS:
          return false;
        case exports.ChannelClass.GYROSCOPE:
          return false;
        case exports.ChannelClass.HUB:
          return false;
        case exports.ChannelClass.HUMIDITY_SENSOR:
          return false;
        case exports.ChannelClass.IR:
          return false;
        case exports.ChannelClass.LCD:
          return true;
        case exports.ChannelClass.LEDARRAY:
          return true;
        case exports.ChannelClass.LIGHT_SENSOR:
          return false;
        case exports.ChannelClass.MAGNETOMETER:
          return false;
        case exports.ChannelClass.MOTOR_POSITION_CONTROLLER:
          return false;
        case exports.ChannelClass.MOTOR_VELOCITY_CONTROLLER:
          return false;
        case exports.ChannelClass.PH_SENSOR:
          return false;
        case exports.ChannelClass.POWER_GUARD:
          return true;
        case exports.ChannelClass.PRESSURE_SENSOR:
          return false;
        case exports.ChannelClass.RC_SERVO:
          return true;
        case exports.ChannelClass.RESISTANCE_INPUT:
          return false;
        case exports.ChannelClass.RFID:
          return false;
        case exports.ChannelClass.SOUND_SENSOR:
          return false;
        case exports.ChannelClass.SPATIAL:
          return false;
        case exports.ChannelClass.STEPPER:
          return true;
        case exports.ChannelClass.TEMPERATURE_SENSOR:
          return false;
        case exports.ChannelClass.VOLTAGE_INPUT:
          return false;
        case exports.ChannelClass.VOLTAGE_OUTPUT:
          return true;
        case exports.ChannelClass.VOLTAGE_RATIO_INPUT:
          return false;
        default:
          throw new Error("Invalid Channel Class");
      }
    }

    /** @public */
    class Phidget extends PhidgetBase {
      /** @internal */
      _fromManager;
      /** @internal */
      _isattached;
      onAttach;
      onDetach;
      /**
      * **Error** event
      *
      *  * `code` - The error code
      *  * `msg` - The error description
      * ---
      * Error is called when an error condition has been detected.
      *
      * See the documentation for your specific channel class to see what error events it might throw.
      * @param code - The error code
      * @param description - The error description
      */
      onError;
      /**
      * **PropertyChange** event
      *
      *  * `propertyName` - The name of the property that has changed
      * ---
      * Occurs when a property is changed externally from the user channel, usually from a network client attached to the same channel.
      * @param propertyName - The name of the property that has changed
      */
      onPropertyChange;
      name;
      /**
       * Gets the version of the Phidget library being used by the program in human readable form.
       * @returns The Phidget library version.
       * @throws `PhidgetError`
       */
      static get libraryVersion() {
        return this.getLibraryVersion();
      }
      /**
       * Gets the version of the Phidget library being used by the program in human readable form.
       * @returns The Phidget library version.
       * @throws `PhidgetError`
       */
      static getLibraryVersion() {
        return LibraryVersion;
      }
      /** @internal */
      constructor(chOrDev) {
        super();
        this.onAttach = null;
        this.onDetach = null;
        this.onError = null;
        this.onPropertyChange = null;
        if (chOrDev !== undefined) {
          this._fromManager = true;
          this._isattached = true;
        } else {
          this._fromManager = false;
          this._isattached = false;
        }
      }
    }
    /** @public */
    class PhidgetChannel extends Phidget {
      /** @internal */
      _class;
      /** @internal */
      _isopen;
      /** @internal */
      _attaching;
      /** @internal */
      _useropen;
      /** @internal */
      _detaching;
      /** @internal */
      _ch;
      /** @internal */
      _openTimeout;
      /** @internal */
      _openTime;
      /** @internal */
      _openTimeoutTimer;
      /** @internal */
      _channel;
      /** @internal */
      _deviceLabel;
      /** @internal */
      _serialNumber;
      /** @internal */
      _hubPort;
      /** @internal */
      _isHubPort;
      /** @internal */
      _isLocal;
      /** @internal */
      _isRemote;
      /** @internal */
      _persistence;
      /** @internal */
      _rejectOpen;
      /** @internal */
      _resolveOpen;
      /** @internal */
      _onInitialState;
      /** @internal */
      constructor(ch) {
        super(ch);
        this._attaching = false;
        this._useropen = false;
        this._isopen = false;
        this._detaching = false;
        this._isHubPort = false;
        this._channel = Phidget.ANY_CHANNEL;
        this._deviceLabel = Phidget.ANY_LABEL;
        this._serialNumber = Phidget.ANY_SERIAL_NUMBER;
        this._hubPort = Phidget.ANY_HUB_PORT;
        this._isLocal = false;
        this._isRemote = false;
        this._persistence = false;
        this._ch = ch;
      }
      /** @internal */
      _cancelOpenTimeout() {
        if (this._openTimeoutTimer != undefined) {
          clearTimeout(this._openTimeoutTimer);
          delete this._openTimeoutTimer;
        }
        delete this._openTimeout;
        delete this._openTime;
      }
      /** @internal */
      async _wasOpened(ch) {
        this._ch = ch;
        this._isopen = true;
        this._isattached = true;
        this._cancelOpenTimeout();
        if (this.onAttach) {
          try {
            await this.onAttach(this);
          } catch (err) {
            logEventException(err);
          }
        }
        if (this._resolveOpen) this._resolveOpen();
      }
      /** @internal */
      async _close(fromDetach = false) {
        this._cancelOpenTimeout();
        if (fromDetach) {
          this._useropen = true;
        } else {
          if (_includesInstanceProperty(UserPhidgets).call(UserPhidgets, this)) UserPhidgets.splice(UserPhidgets.indexOf(this), 1);
          if (UserPhidgets.length === 0) await stopScanningUserPhidgets();
        }
        if (this._isopen) {
          try {
            if (this._ch) await this._ch.close();
          } catch (err) {
            logwarn("Error while closing channel", err);
          }
          this._detaching = true;
          this._isattached = false;
          if (this.onDetach) {
            try {
              this.onDetach(this);
            } catch (err) {
              logEventException(err);
            }
          }
          this._detaching = false;
          this._isopen = false;
          delete this._ch;
        } else {
          if (this._rejectOpen != undefined) this._rejectOpen(new PhidgetError(exports.ErrorCode.CLOSED, "Closed while waiting for open"));
        }
      }
      /** @internal */
      _FIREPropertyChange(prop, bp) {
        if (this.onPropertyChange && this._isAttachedDone && (bp === undefined || bp.local !== true)) {
          try {
            this.onPropertyChange(prop);
          } catch (err) {
            logEventException(err);
          }
        }
      }
      /** @internal */
      _FIREError(code, description) {
        if (this.onError) {
          try {
            this.onError(code, description);
          } catch (err) {
            logEventException(err);
          }
        }
      }
      /** @internal */
      _handleSetStatus(bp) {
        for (const e in bp.entries) {
          if (e === '_class_version_') continue;
          if (e === 'dataIntervalDbl') continue;
          if (!(e in this.data)) {
            loginfo("Unknown property: " + e + " in setstatus packet. Probably server is newer than client.");
            continue;
          }
          this.data[e] = bp.entries[e].v;
        }
        if (bp.entries.dataIntervalDbl !== undefined) this.data.dataInterval = bp.entries.dataIntervalDbl.v;
        if (this.data.minDataInterval != undefined && bp.entries.maxDataRate === undefined) this.data.maxDataRate = 1000.0 / this.data.minDataInterval;
        if (this.data.maxDataInterval != undefined && bp.entries.minDataRate === undefined) this.data.minDataRate = 1000.0 / this.data.maxDataInterval;
      }
      /** @internal */
      _assertAttached() {
        if (!this._ch || !this._isattached && !this._detaching) throw new PhidgetError(exports.ErrorCode.NOT_ATTACHED);
      }
      /** @internal */
      _assertOpen() {
        if (!this._ch || !this._isopen || !this._isattached && !this._detaching) throw new PhidgetError(exports.ErrorCode.NOT_ATTACHED);
      }
      /** @internal */
      get _isAttachedDone() {
        if (this._isattached && !this._attaching) return true;
        return false;
      }
      /** @internal */
      get _isAttachedOrDetaching() {
        if (this._isattached || this._detaching) return true;
        return false;
      }
      toString() {
        if (this._ch) return this._ch.toString();
        return this.constructor.name;
      }
      getConnection() {
        if (this._ch) return this._ch.conn;
        return null;
      }
      getKey() {
        this._assertAttached();
        return 'ch' + this._ch.id + "_" + this._ch.conn._id;
      }
      async open(timeout = 0) {
        if (this._useropen) return;
        this._useropen = true;
        this._openTime = tm();
        if (!isNaN(timeout) && timeout > 0) this._openTimeout = timeout;else delete this._openTimeout;
        UserPhidgets.push(this);
        if (this._fromManager === true) {
          this.setChannel(this.getChannel());
          this.setHubPort(this.getHubPort());
          this.setDeviceSerialNumber(this.getDeviceSerialNumber());
          this.setIsHubPortDevice(this.getIsHubPortDevice());
          this.setIsLocal(this.getIsLocal());
          this.setIsRemote(this.getIsRemote());
          this._fromManager = false;
          this._isattached = false;
          delete this._ch;
        }
        const openPromise = new Promise((resolve, reject) => {
          this._resolveOpen = resolve;
          this._rejectOpen = reject;
        });
        try {
          await scanChannels(this);
        } catch (err) {
          logerr("Problem during open scan", err);
        }
        await startScanningUserPhidgets();
        if (this._openTimeout) {
          this._openTimeoutTimer = setTimeout(() => {
            delete this._openTimeoutTimer;
            const reject = this._rejectOpen;
            delete this._rejectOpen;
            this.close().then(() => {
              if (reject) reject(new PhidgetError(exports.ErrorCode.TIMEOUT, "Open timed out"));
            }).catch(err => {
              logwarn("Error calling close after open timeout", err);
              if (reject) reject(new PhidgetError(exports.ErrorCode.TIMEOUT, "Open timed out"));
            });
          }, this._openTimeout);
        }
        return openPromise;
      }
      async close() {
        if (this._useropen) {
          logdebug("closing phidget");
          this._useropen = false;
          await this._close();
        }
      }
      getAttached() {
        return this._isattached;
      }
      getIsOpen() {
        return this._useropen;
      }
      getChannel() {
        if (!this._isattached && !this._detaching) return this._channel;
        return this._ch.index;
      }
      setChannel(ch) {
        this._channel = ch;
      }
      getChannelClass() {
        return this._class;
      }
      getChannelClassName() {
        return ChannelClassName[this._class];
      }
      getChannelName() {
        this._assertAttached();
        return this._ch.name;
      }
      getChannelSubclass() {
        this._assertAttached();
        return this._ch.subclass;
      }
      getDeviceClass() {
        this._assertAttached();
        return this._ch.parent.class;
      }
      getDeviceClassName() {
        this._assertAttached();
        return DeviceClassName[this._ch.parent.class];
      }
      getDeviceID() {
        this._assertAttached();
        return this._ch.parent.deviceID;
      }
      getDeviceLabel() {
        if (!this._isattached && !this._detaching) return this._deviceLabel ? this._deviceLabel : '';
        return this._ch.parent.label;
      }
      setDeviceLabel(label) {
        this._deviceLabel = label;
      }
      getDeviceName() {
        this._assertAttached();
        return this._ch.parent.name;
      }
      getDeviceSerialNumber() {
        if (!this._isattached && !this._detaching) return this._serialNumber;
        return this._ch.parent.serialNumber;
      }
      setDeviceSerialNumber(sn) {
        if (!isNaN(sn)) this._serialNumber = sn;
      }
      getDeviceSKU() {
        this._assertAttached();
        return this._ch.parent.sku;
      }
      getDeviceVersion() {
        this._assertAttached();
        return this._ch.parent.version;
      }
      getHub() {
        this._assertAttached();
        let hub = this._ch.parent;
        while (hub != undefined && hub.class !== exports.DeviceClass.HUB) hub = hub.parent;
        if (hub == undefined) throw new PhidgetError(exports.ErrorCode.WRONG_DEVICE, "Hub not found");
        return new PhidgetDevice(hub);
      }
      getHubPort() {
        if (!this._isattached && !this._detaching) return this._hubPort;
        return this._ch.parent.hubPort;
      }
      setHubPort(hubPort) {
        if (!isNaN(hubPort)) this._hubPort = hubPort;
      }
      getHubPortSpeed() {
        this._assertAttached();
        if (this._ch.parent.class !== exports.DeviceClass.VINT) throw new PhidgetError(exports.ErrorCode.WRONG_DEVICE);
        if (this._ch.parent.vintDeviceProps.commSpeed == undefined || this._ch.parent.vintDeviceProps.commSpeed == 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this._ch.parent.vintDeviceProps.commSpeed;
      }
      async setHubPortSpeed(hubPortSpeed) {
        this._assertAttached();
        if (this._ch.parent.class !== exports.DeviceClass.VINT) throw new PhidgetError(exports.ErrorCode.WRONG_DEVICE);
        const bp = new BridgePacket();
        bp.set({
          name: '0',
          type: 'u',
          value: hubPortSpeed
        });
        await bp.send(this._ch, 173);
      }
      getIsChannel() {
        return true;
      }
      getIsHubPortDevice() {
        if (!this._isattached && !this._detaching) return this._isHubPort;
        return this._ch.parent.isHubPort;
      }
      setIsHubPortDevice(isHubPort) {
        this._isHubPort = isHubPort;
      }
      getIsLocal() {
        if (!this._isattached && !this._detaching) return this._isLocal;
        return this._ch.parent.conn._isLocal;
      }
      setIsLocal(isLocal) {
        this._isLocal = isLocal;
      }
      getIsRemote() {
        if (!this._isattached && !this._detaching) return this._isRemote;
        return this._ch.parent.conn._isRemote;
      }
      setIsRemote(isRemote) {
        this._isRemote = isRemote;
      }
      getParent() {
        this._assertAttached();
        return new PhidgetDevice(this._ch.parent);
      }
      getDeviceFirmwareUpgradeString() {
        this._assertAttached();
        return this._ch.parent.fwstr;
      }
      async writeDeviceLabel(deviceLabel) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "s",
          value: deviceLabel
        });
        await bp.send(this._ch, 140);
      }
      getDeviceChannelCount(cls) {
        this._assertAttached();
        let count = 0;
        for (const ch of this._ch.parent.devDef.ch) {
          if (cls != undefined && ch.c == undefined) throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
          if (cls == undefined || ch.c === cls) count++;
        }
        return count;
      }
      getDeviceVINTID() {
        this._assertAttached();
        if (this.deviceClass !== exports.DeviceClass.VINT) throw new PhidgetError(exports.ErrorCode.WRONG_DEVICE);
        return this._ch.parent.vintID;
      }
      getHubPortCount() {
        this._assertAttached();
        if (this.deviceClass !== exports.DeviceClass.VINT && this.deviceClass !== exports.DeviceClass.HUB) throw new PhidgetError(exports.ErrorCode.WRONG_DEVICE);
        return this.hub._device.hubPortProps.length;
      }
      getHubPortSupportsSetSpeed() {
        this._assertAttached();
        if (this.deviceClass !== exports.DeviceClass.VINT) throw new PhidgetError(exports.ErrorCode.WRONG_DEVICE);
        return this.hub._device.hubPortProps[this.hubPort].portSuppSetSpeed;
      }
      getHubPortSupportsAutoSetSpeed() {
        this._assertAttached();
        if (this.deviceClass !== exports.DeviceClass.VINT) throw new PhidgetError(exports.ErrorCode.WRONG_DEVICE);
        return this.hub._device.hubPortProps[this.hubPort].portSuppAutoSetSpeed;
      }
      getMaxHubPortSpeed() {
        this._assertAttached();
        if (this.deviceClass !== exports.DeviceClass.VINT) throw new PhidgetError(exports.ErrorCode.WRONG_DEVICE);
        if (this.hub._device.hubPortProps[this.hubPort].portMaxSpeed === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.hub._device.hubPortProps[this.hubPort].portMaxSpeed;
      }
      getVINTDeviceSupportsSetSpeed() {
        this._assertAttached();
        if (this.deviceClass !== exports.DeviceClass.VINT) throw new PhidgetError(exports.ErrorCode.WRONG_DEVICE);
        return this._ch.parent.vintDeviceProps.suppSetSpeed;
      }
      getVINTDeviceSupportsAutoSetSpeed() {
        this._assertAttached();
        if (this.deviceClass !== exports.DeviceClass.VINT) throw new PhidgetError(exports.ErrorCode.WRONG_DEVICE);
        return this._ch.parent.vintDeviceProps.suppAutoSetSpeed;
      }
      getMaxVINTDeviceSpeed() {
        this._assertAttached();
        if (this.deviceClass !== exports.DeviceClass.VINT) throw new PhidgetError(exports.ErrorCode.WRONG_DEVICE);
        if (this._ch.parent.vintDeviceProps.maxSpeed === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this._ch.parent.vintDeviceProps.maxSpeed;
      }
      async reboot() {
        this._assertOpen();
        const bp = new BridgePacket();
        await bp.send(this._ch, 139, false);
      }
      async rebootFirmwareUpgrade(upgradeTimeout) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: upgradeTimeout
        });
        await bp.send(this._ch, 138, false);
      }
      getChannelPersistence() {
        if (this._isattached || this._detaching) return this._ch.persistence;
        return this._persistence;
      }
      async setChannelPersistence(channelPersistence) {
        if (!AllowChannelPersistence(this.channelClass)) throw new PhidgetError(exports.ErrorCode.UNSUPPORTED, "Channel persistence is not supported for this channel class");
        this._persistence = channelPersistence;
        if (this._isopen && this._isattached) {
          const bp = new BridgePacket();
          bp.set({
            name: "0",
            type: "d",
            value: channelPersistence ? 1 : 0
          });
          await bp.send(this._ch, 211);
        }
      }
    }
    /** @public */
    class PhidgetDevice extends Phidget {
      /** @internal */
      _device;
      /** @internal */
      constructor(dev) {
        super(dev);
        this._device = dev;
        this.name = "PhidgetDevice";
      }
      toString() {
        return this._device.toString();
      }
      getConnection() {
        return this._device.conn;
      }
      getKey() {
        return 'dev' + this._device.id + "_" + this._device.conn._id;
      }
      getAttached() {
        return true;
      }
      getIsOpen() {
        return false;
      }
      getDeviceClass() {
        return this._device.class;
      }
      getDeviceClassName() {
        return DeviceClassName[this._device.class];
      }
      getDeviceID() {
        return this._device.deviceID;
      }
      getDeviceLabel() {
        return this._device.label;
      }
      getDeviceName() {
        return this._device.name;
      }
      getDeviceSerialNumber() {
        return this._device.serialNumber;
      }
      getDeviceSKU() {
        return this._device.sku;
      }
      getDeviceVersion() {
        return this._device.version;
      }
      getHub() {
        let hub = this._device;
        while (hub != undefined && hub.class !== exports.DeviceClass.HUB) hub = hub.parent;
        if (hub == undefined) throw new PhidgetError(exports.ErrorCode.WRONG_DEVICE, "Hub not found");
        return new PhidgetDevice(hub);
      }
      getHubPort() {
        return this._device.hubPort;
      }
      getHubPortSpeed() {
        if (this._device.class !== exports.DeviceClass.VINT) throw new PhidgetError(exports.ErrorCode.WRONG_DEVICE);
        if (this._device.vintDeviceProps.commSpeed == undefined || this._device.vintDeviceProps.commSpeed == 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this._device.vintDeviceProps.commSpeed;
      }
      getIsChannel() {
        return false;
      }
      getIsHubPortDevice() {
        return this._device.isHubPort;
      }
      getIsLocal() {
        return this._device.conn._isLocal;
      }
      getIsRemote() {
        return this._device.conn._isRemote;
      }
      getParent() {
        const parent = this._device.parent;
        if (!parent) return null;
        return new PhidgetDevice(parent);
      }
      getDeviceFirmwareUpgradeString() {
        return this._device.fwstr;
      }
      getDeviceChannelCount(cls) {
        let count = 0;
        for (const ch of this._device.devDef.ch) {
          if (cls != undefined && ch.c == undefined) throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
          if (cls == undefined || ch.c === cls) count++;
        }
        return count;
      }
      getDeviceVINTID() {
        if (this.deviceClass !== exports.DeviceClass.VINT) throw new PhidgetError(exports.ErrorCode.WRONG_DEVICE);
        return this._device.vintID;
      }
      getHubPortCount() {
        if (this.deviceClass !== exports.DeviceClass.VINT && this.deviceClass !== exports.DeviceClass.HUB) throw new PhidgetError(exports.ErrorCode.WRONG_DEVICE);
        return this.hub._device.hubPortProps.length;
      }
      getHubPortSupportsSetSpeed() {
        if (this.deviceClass !== exports.DeviceClass.VINT) throw new PhidgetError(exports.ErrorCode.WRONG_DEVICE);
        return this.hub._device.hubPortProps[this.hubPort].portSuppSetSpeed;
      }
      getHubPortSupportsAutoSetSpeed() {
        if (this.deviceClass !== exports.DeviceClass.VINT) throw new PhidgetError(exports.ErrorCode.WRONG_DEVICE);
        return this.hub._device.hubPortProps[this.hubPort].portSuppAutoSetSpeed;
      }
      getMaxHubPortSpeed() {
        if (this.deviceClass !== exports.DeviceClass.VINT) throw new PhidgetError(exports.ErrorCode.WRONG_DEVICE);
        if (this.hub._device.hubPortProps[this.hubPort].portMaxSpeed === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.hub._device.hubPortProps[this.hubPort].portMaxSpeed;
      }
      getVINTDeviceSupportsSetSpeed() {
        if (this.deviceClass !== exports.DeviceClass.VINT) throw new PhidgetError(exports.ErrorCode.WRONG_DEVICE);
        return this._device.vintDeviceProps.suppSetSpeed;
      }
      getVINTDeviceSupportsAutoSetSpeed() {
        if (this.deviceClass !== exports.DeviceClass.VINT) throw new PhidgetError(exports.ErrorCode.WRONG_DEVICE);
        return this._device.vintDeviceProps.suppAutoSetSpeed;
      }
      getMaxVINTDeviceSpeed() {
        if (this.deviceClass !== exports.DeviceClass.VINT) throw new PhidgetError(exports.ErrorCode.WRONG_DEVICE);
        if (this._device.vintDeviceProps.maxSpeed === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this._device.vintDeviceProps.maxSpeed;
      }
      getChannel() {
        throw new PhidgetError(exports.ErrorCode.UNEXPECTED);
      }
      setChannel(_channel) {
        throw new PhidgetError(exports.ErrorCode.UNEXPECTED);
      }
      getChannelClass() {
        throw new PhidgetError(exports.ErrorCode.UNEXPECTED);
      }
      getChannelClassName() {
        throw new PhidgetError(exports.ErrorCode.UNEXPECTED);
      }
      getChannelName() {
        throw new PhidgetError(exports.ErrorCode.UNEXPECTED);
      }
      getChannelSubclass() {
        throw new PhidgetError(exports.ErrorCode.UNEXPECTED);
      }
      close() {
        throw new PhidgetError(exports.ErrorCode.UNEXPECTED);
      }
      setDeviceLabel(_deviceLabel) {
        throw new PhidgetError(exports.ErrorCode.UNEXPECTED);
      }
      setDeviceSerialNumber(_deviceSerialNumber) {
        throw new PhidgetError(exports.ErrorCode.UNEXPECTED);
      }
      setHubPort(_hubPort) {
        throw new PhidgetError(exports.ErrorCode.UNEXPECTED);
      }
      setHubPortSpeed(_hubPortSpeed) {
        throw new PhidgetError(exports.ErrorCode.UNEXPECTED);
      }
      setIsHubPortDevice(_isHubPortDevice) {
        throw new PhidgetError(exports.ErrorCode.UNEXPECTED);
      }
      setIsLocal(_isLocal) {
        throw new PhidgetError(exports.ErrorCode.UNEXPECTED);
      }
      setIsRemote(_isRemote) {
        throw new PhidgetError(exports.ErrorCode.UNEXPECTED);
      }
      open(_timeout) {
        throw new PhidgetError(exports.ErrorCode.UNEXPECTED);
      }
      writeDeviceLabel(_deviceLabel) {
        throw new PhidgetError(exports.ErrorCode.UNEXPECTED);
      }
      reboot() {
        throw new PhidgetError(exports.ErrorCode.UNEXPECTED);
      }
      rebootFirmwareUpgrade(_upgradeTimeout) {
        throw new PhidgetError(exports.ErrorCode.UNEXPECTED);
      }
      getChannelPersistence() {
        throw new PhidgetError(exports.ErrorCode.UNEXPECTED);
      }
      setChannelPersistence(_channelPersistence) {
        throw new PhidgetError(exports.ErrorCode.UNEXPECTED);
      }
    }

    /** @internal */
    class Channel {
      parent;
      conn;
      isopen;
      id;
      uniqueIndex;
      index;
      chDef;
      persistence;
      userphid;
      detaching;
      lastErrorEventCode = null;
      lastErrorEventDesc = '';
      lastErrorEventTime = 0;
      get subclass() {
        return this.chDef.s ?? exports.ChannelSubclass.NONE;
      }
      get isHubPort() {
        return this.parent.isHubPort;
      }
      constructor(conn, dev, data) {
        this.conn = conn;
        this.parent = dev;
        this.id = data.id;
        this.chDef = data.chDef;
        this.uniqueIndex = data.uniqueIndex;
        this.index = data.index;
        this.isopen = false;
        this.persistence = false;
      }
      match(userphid) {
        if (userphid._attaching || userphid._isattached) return false;
        if (userphid._class !== this.class) return false;
        if (userphid._serialNumber !== Phidget.ANY_SERIAL_NUMBER) {
          if (userphid._serialNumber != this.parent.serialNumber) return false;
        }
        if (userphid._channel !== Phidget.ANY_CHANNEL) {
          if (userphid._channel != this.index) return false;
        }
        if (userphid._hubPort !== Phidget.ANY_HUB_PORT) {
          if (userphid._hubPort != this.parent.hubPort) return false;
        }
        if (userphid._isHubPort !== this.isHubPort) return false;
        if (userphid._deviceLabel !== Phidget.ANY_LABEL) {
          if (userphid._deviceLabel !== this.parent.label) return false;
        }
        if (userphid._isLocal && this.conn._isRemote) return false;
        if (userphid._isRemote && this.conn._isLocal) return false;
        logdebug("matched:" + userphid + " -> " + this);
        return true;
      }
      async tryMatchOpen(userphid) {
        if (this.match(userphid)) {
          try {
            await this.open(userphid);
            return true;
          } catch (err) {
            if (userphid.onError) {
              try {
                if (err instanceof PhidgetError) {
                  let code;
                  switch (err.errorCode) {
                    case exports.ErrorCode.BUSY:
                      code = exports.ErrorEventCode.BUSY;
                      break;
                    case exports.ErrorCode.BAD_VERSION:
                      code = exports.ErrorEventCode.BAD_VERSION;
                      break;
                    case exports.ErrorCode.FAILSAFE:
                      code = exports.ErrorEventCode.FAILSAFE_CONDITION;
                      break;
                    case exports.ErrorCode.UNKNOWN_VALUE:
                      code = exports.ErrorEventCode.OUT_OF_RANGE;
                      break;
                    case exports.ErrorCode.UNKNOWN_VALUE_HIGH:
                      code = exports.ErrorEventCode.OUT_OF_RANGE_HIGH_CONDITION;
                      break;
                    case exports.ErrorCode.UNKNOWN_VALUE_LOW:
                      code = exports.ErrorEventCode.OUT_OF_RANGE_LOW_CONDITION;
                      break;
                    case exports.ErrorCode.BAD_POWER:
                    case exports.ErrorCode.POWER_CYCLE:
                      code = exports.ErrorEventCode.BAD_POWER;
                      break;
                    case exports.ErrorCode.HALLSENSOR:
                    case exports.ErrorCode.BADCONNECTION:
                      code = exports.ErrorEventCode.BAD_CONNECTION_CONDITION;
                      break;
                    case exports.ErrorCode.BADCURRENT:
                      code = exports.ErrorEventCode.BAD_CURRENT;
                      break;
                    default:
                      code = exports.ErrorEventCode.FAILURE;
                      break;
                  }
                  userphid.onError(code, err.message);
                } else if (err instanceof Error) {
                  userphid.onError(exports.ErrorEventCode.FAILURE, err.message);
                } else {
                  userphid.onError(exports.ErrorEventCode.FAILURE, "Error during open");
                }
              } catch (err) {
                logEventException(err);
              }
            } else {
              logerr("Error opening channel", err);
            }
          }
        }
        return false;
      }
      detach() {
        if (this.isopen) {
          if (this.userphid) {
            this.detaching = true;
            this.userphid._close(true).then(() => {
              this.isopen = false;
              delete this.userphid;
              delete this.detaching;
            }).catch(err => {
              this.isopen = false;
              delete this.userphid;
              delete this.detaching;
              logwarn("Error closing during detach", err);
            });
          }
        }
      }
      toString() {
        if (this.parent.class === exports.DeviceClass.VINT) {
          if (this.isHubPort) return this.name + ' Ch:' + this.index + ' -> ' + this.parent.sku + ' Port:' + this.parent.hubPort + ' Serial#:' + this.parent.serialNumber;
          return this.name + ' Ch:' + this.index + ' -> ' + this.parent.sku + ' -> ' + this.parent.parent.sku + ' Port:' + this.parent.hubPort + ' Serial#:' + this.parent.serialNumber;
        }
        return this.name + ' Ch:' + this.index + ' -> ' + this.parent.sku + ' Serial#:' + this.parent.serialNumber;
      }
      supportedBridgePacket(bp) {
        var _context;
        if (this.chDef.p == undefined || _includesInstanceProperty(_context = this.chDef.p).call(_context, bp)) return true;
        return false;
      }
      bridgeInput(bp) {
        if (!this.userphid) return;
        switch (bp.vpkt) {
          case 0:
            this.userphid._handleSetStatus(bp);
            break;
          case 17:
            if (this.userphid._errorHandler) this.userphid._errorHandler(bp.getNumber(0));
            if (this.userphid.onError) {
              try {
                this.userphid.onError(bp.getNumber(0), bp.getString(1));
              } catch (err) {
                logEventException(err);
              }
            }
            break;
          case 172:
            this.parent.label = bp.getString(0);
            this.userphid._FIREPropertyChange('DeviceLabel', bp);
            break;
          case 176:
            this.parent.vintDeviceProps.commSpeed = bp.getNumber(0);
            this.userphid._FIREPropertyChange('HubPortSpeed', bp);
            break;
          case 139:
          case 138:
            break;
          case 173:
            if (this.conn._isRemote) this.parent.vintDeviceProps.commSpeed = bp.getNumber(0);
            break;
          case 140:
            if (this.conn._isRemote) this.parent.label = bp.getString(0);
            break;
          case 211:
            this.persistence = !!bp.getNumber(0);
            this.userphid._FIREPropertyChange('ChannelPersistence', bp);
            break;
          default:
            {
              if (!this.supportedBridgePacket(bp.vpkt)) throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
              this.userphid._bridgeInput(bp);
              if (this.userphid._onInitialState && this.userphid._hasInitialState()) this.userphid._onInitialState();
              break;
            }
        }
      }
      sendErrorEvent(bp) {
        const code = bp.getNumber(0);
        const desc = bp.getString(1);
        const now = Date.now();
        if (this.lastErrorEventCode === code && this.lastErrorEventDesc === desc) {
          if (now - this.lastErrorEventTime < 1000) return;
        }
        this.lastErrorEventCode = code;
        this.lastErrorEventDesc = desc;
        this.lastErrorEventTime = now;
        bp.vpkt = 17;
        this.bridgeInput(bp);
      }
      clearErrorEvent() {
        this.lastErrorEventCode = null;
      }
    }

    /** @internal */
    class NetworkChannel extends Channel {
      cpversion;
      name;
      class;
      constructor(conn, dev, data) {
        super(conn, dev, data);
        this.cpversion = data.cpversion;
        this.name = data.name;
        this.class = data.class;
      }
      async open(userphid) {
        try {
          this.persistence = userphid._persistence;
          const devInfo = {
            phid: this.parent.id,
            channel: this.id,
            class: this.class,
            index: this.uniqueIndex,
            version: this.cpversion,
            chreset: this.persistence ? 0 : 1
          };
          userphid._attaching = true;
          const status = await this.conn._sendRequest(0, 0, 0, 30, 60, devInfo);
          userphid._attaching = false;
          this.isopen = true;
          this.userphid = userphid;
          const bp = new BridgePacket(this.conn, status);
          bp.deliver();
          await userphid._wasOpened(this);
        } catch (err) {
          userphid._attaching = false;
          userphid._isattached = false;
          throw err;
        }
      }
      async close() {
        if (this.detaching) return;
        const closePkt = {
          phid: this.parent.id,
          index: this.uniqueIndex,
          chreset: this.persistence ? 0 : 1
        };
        await this.conn._sendRequest(0, 0, 0, 30, 65, closePkt);
      }
      async send(bp) {
        const pkt = bp.getJsonOut(this);
        const response = await this.conn._sendRequest(0, 0, 0, 30, 70, pkt);
        return response;
      }
    }

    /** @internal */
    const PhidgetDevices = {
      VINT: [{
        uid: 23,
        c: 21,
        s: "1014",
        i: 64,
        v: [800, 900],
        ch: [{
          uid: 41,
          n: 4
        }]
      }, {
        uid: 28,
        c: 21,
        s: "1017",
        i: 135,
        v: [200, 300],
        ch: [{
          uid: 46,
          n: 8
        }]
      }, {
        uid: 37,
        c: 21,
        s: "1024",
        i: 57,
        v: [300, 310],
        ch: [{
          uid: 73
        }, {
          uid: 74
        }, {
          uid: 75
        }, {
          uid: 76
        }]
      }, {
        uid: 38,
        c: 21,
        s: "1024",
        i: 57,
        v: [310, 320],
        ch: [{
          uid: 77
        }, {
          uid: 78
        }, {
          uid: 79
        }, {
          uid: 80
        }]
      }, {
        uid: 39,
        c: 21,
        s: "1024",
        i: 57,
        v: [320, 400],
        ch: [{
          uid: 81
        }, {
          uid: 82
        }, {
          uid: 83
        }, {
          uid: 84
        }]
      }, {
        uid: 95,
        c: 21,
        s: "ADP0001",
        i: 134,
        v: [200, 300],
        ch: [{
          uid: 204
        }, {
          uid: 205,
          n: 2
        }, {
          uid: 206,
          n: 2
        }]
      }, {
        uid: 97,
        c: 21,
        s: "ADP0002",
        i: 160,
        v: [100, 200],
        ch: [{
          uid: 210
        }, {
          uid: 211,
          n: 2
        }, {
          uid: 212,
          n: 2
        }]
      }, {
        uid: 100,
        c: 21,
        s: "ADP1000",
        i: 29,
        v: [100, 200],
        ch: [{
          uid: 215
        }, {
          uid: 216
        }]
      }, {
        uid: 105,
        c: 21,
        s: "DAQ1000",
        i: 50,
        v: [100, 110],
        ch: [{
          uid: 223,
          s: 64,
          n: 8
        }, {
          uid: 224,
          s: 48,
          n: 8
        }]
      }, {
        uid: 106,
        c: 21,
        s: "DAQ1000",
        i: 50,
        v: [110, 200],
        ch: [{
          uid: 225,
          s: 64,
          n: 8
        }, {
          uid: 226,
          s: 48,
          n: 8
        }]
      }, {
        uid: 107,
        c: 21,
        s: "DAQ1001",
        i: 131,
        v: [100, 200],
        ch: [{
          uid: 227,
          s: 64,
          n: 8
        }, {
          uid: 228,
          s: 48,
          n: 8
        }]
      }, {
        uid: 108,
        c: 21,
        s: "DAQ1200",
        i: 28,
        v: [100, 200],
        ch: [{
          uid: 229,
          n: 4
        }]
      }, {
        uid: 109,
        c: 21,
        s: "DAQ1300",
        i: 32,
        v: [100, 200],
        ch: [{
          uid: 230,
          n: 4
        }]
      }, {
        uid: 110,
        c: 21,
        s: "DAQ1301",
        i: 54,
        v: [100, 200],
        ch: [{
          uid: 231,
          n: 16
        }]
      }, {
        uid: 111,
        c: 21,
        s: "DAQ1400",
        i: 34,
        v: [100, 120],
        ch: [{
          uid: 232
        }, {
          uid: 233
        }, {
          uid: 234
        }, {
          uid: 235
        }]
      }, {
        uid: 112,
        c: 21,
        s: "DAQ1400",
        i: 34,
        v: [120, 130],
        ch: [{
          uid: 236
        }, {
          uid: 237
        }, {
          uid: 238
        }, {
          uid: 239
        }]
      }, {
        uid: 113,
        c: 21,
        s: "DAQ1400",
        i: 34,
        v: [130, 200],
        ch: [{
          uid: 240
        }, {
          uid: 241
        }, {
          uid: 242
        }, {
          uid: 243
        }]
      }, {
        uid: 114,
        c: 21,
        s: "DAQ1500",
        i: 24,
        v: [100, 200],
        ch: [{
          uid: 244,
          s: 65,
          n: 2
        }]
      }, {
        uid: 115,
        c: 21,
        s: "DCC1000",
        i: 47,
        v: [100, 200],
        ch: [{
          uid: 245
        }, {
          uid: 246,
          s: 96
        }, {
          uid: 247,
          s: 64
        }, {
          uid: 248
        }, {
          uid: 249
        }]
      }, {
        uid: 116,
        c: 21,
        s: "DCC1000",
        i: 47,
        v: [200, 210],
        ch: [{
          uid: 250
        }, {
          uid: 251,
          s: 96
        }, {
          uid: 252,
          s: 64
        }, {
          uid: 253
        }, {
          uid: 254
        }, {
          uid: 255
        }]
      }, {
        uid: 117,
        c: 21,
        s: "DCC1000",
        i: 47,
        v: [210, 300],
        ch: [{
          uid: 256
        }, {
          uid: 257,
          s: 96
        }, {
          uid: 258,
          s: 64
        }, {
          uid: 259
        }, {
          uid: 260
        }, {
          uid: 261
        }]
      }, {
        uid: 118,
        c: 21,
        s: "DCC1001",
        i: 68,
        v: [100, 120],
        ch: [{
          uid: 262
        }, {
          uid: 263
        }, {
          uid: 264
        }]
      }, {
        uid: 119,
        c: 21,
        s: "DCC1001",
        i: 68,
        v: [120, 200],
        ch: [{
          uid: 265
        }, {
          uid: 266
        }, {
          uid: 267
        }]
      }, {
        uid: 120,
        c: 21,
        s: "DCC1002",
        i: 70,
        v: [100, 110],
        ch: [{
          uid: 268
        }, {
          uid: 269
        }, {
          uid: 270
        }]
      }, {
        uid: 121,
        c: 21,
        s: "DCC1002",
        i: 70,
        v: [110, 200],
        ch: [{
          uid: 271
        }, {
          uid: 272
        }, {
          uid: 273
        }]
      }, {
        uid: 122,
        c: 21,
        s: "DCC1003",
        i: 73,
        v: [100, 110],
        ch: [{
          uid: 274,
          n: 2
        }]
      }, {
        uid: 123,
        c: 21,
        s: "DCC1003",
        i: 73,
        v: [110, 200],
        ch: [{
          uid: 275,
          n: 2
        }]
      }, {
        uid: 124,
        c: 21,
        s: "DCC1020",
        i: 66,
        v: [100, 200],
        ch: [{
          uid: 276
        }, {
          uid: 277
        }, {
          uid: 278
        }, {
          uid: 279
        }, {
          uid: 280
        }, {
          uid: 281
        }, {
          uid: 282
        }]
      }, {
        uid: 125,
        c: 21,
        s: "DCC1030",
        i: 60,
        v: [100, 200],
        ch: [{
          uid: 283
        }, {
          uid: 284
        }, {
          uid: 285
        }, {
          uid: 286
        }, {
          uid: 287
        }, {
          uid: 288
        }, {
          uid: 289
        }]
      }, {
        uid: 126,
        c: 21,
        s: "DCC1100",
        i: 65,
        v: [100, 120],
        ch: [{
          uid: 290
        }, {
          uid: 291
        }, {
          uid: 292
        }]
      }, {
        uid: 127,
        c: 21,
        s: "DCC1100",
        i: 65,
        v: [120, 200],
        ch: [{
          uid: 293
        }, {
          uid: 294
        }, {
          uid: 295
        }]
      }, {
        uid: 128,
        c: 21,
        s: "DCC1100",
        i: 81,
        v: [200, 300],
        ch: [{
          uid: 296
        }, {
          uid: 297
        }, {
          uid: 298
        }]
      }, {
        uid: 129,
        c: 21,
        s: "DCC1120",
        i: 148,
        v: [100, 200],
        ch: [{
          uid: 299
        }, {
          uid: 300
        }, {
          uid: 301
        }, {
          uid: 302
        }, {
          uid: 303
        }, {
          uid: 304
        }, {
          uid: 305
        }]
      }, {
        uid: 130,
        c: 21,
        s: "DCC1130",
        i: 62,
        v: [100, 200],
        ch: [{
          uid: 306
        }, {
          uid: 307
        }, {
          uid: 308
        }, {
          uid: 309
        }, {
          uid: 310
        }, {
          uid: 311
        }, {
          uid: 312
        }]
      }, {
        uid: 131,
        c: 21,
        s: "DST1000",
        i: 45,
        v: [100, 200],
        ch: [{
          uid: 313
        }]
      }, {
        uid: 132,
        c: 21,
        s: "DST1001",
        i: 121,
        v: [100, 200],
        ch: [{
          uid: 314
        }]
      }, {
        uid: 133,
        c: 21,
        s: "DST1002",
        i: 126,
        v: [100, 200],
        ch: [{
          uid: 315
        }]
      }, {
        uid: 134,
        c: 21,
        s: "DST1200",
        i: 46,
        v: [100, 200],
        ch: [{
          uid: 316
        }]
      }, {
        uid: 135,
        c: 21,
        s: "ENC1000",
        i: 18,
        v: [100, 200],
        ch: [{
          uid: 317,
          s: 96
        }]
      }, {
        uid: 136,
        c: 21,
        s: "ENC1001",
        i: 75,
        v: [100, 200],
        ch: [{
          uid: 318
        }]
      }, {
        uid: 137,
        c: 21,
        s: "HIN1000",
        i: 36,
        v: [100, 200],
        ch: [{
          uid: 319,
          n: 7
        }]
      }, {
        uid: 138,
        c: 21,
        s: "HIN1001",
        i: 56,
        v: [100, 200],
        ch: [{
          uid: 320,
          n: 4
        }, {
          uid: 321
        }]
      }, {
        uid: 139,
        c: 21,
        s: "HIN1100",
        i: 37,
        v: [100, 200],
        ch: [{
          uid: 322,
          n: 2
        }, {
          uid: 323
        }]
      }, {
        uid: 140,
        c: 21,
        s: "HIN1101",
        i: 67,
        v: [100, 200],
        ch: [{
          uid: 324
        }, {
          uid: 325
        }]
      }, {
        uid: 152,
        c: 21,
        s: "HUM1000",
        i: 20,
        v: [100, 200],
        ch: [{
          uid: 337
        }, {
          uid: 338
        }]
      }, {
        uid: 153,
        c: 21,
        s: "HUM1001",
        i: 127,
        v: [100, 200],
        ch: [{
          uid: 339
        }, {
          uid: 340
        }]
      }, {
        uid: 154,
        c: 21,
        s: "HUM1100",
        i: 136,
        v: [100, 200],
        ch: [{
          uid: 341
        }]
      }, {
        uid: 155,
        c: 21,
        s: "LCD1100",
        i: 23,
        v: [200, 300],
        ch: [{
          uid: 342,
          s: 80
        }]
      }, {
        uid: 156,
        c: 21,
        s: "LCD1100",
        i: 40,
        v: [100, 200],
        ch: [{
          uid: 343,
          s: 80
        }]
      }, {
        uid: 158,
        c: 21,
        s: "LED0100",
        i: 161,
        v: [100, 200],
        ch: [{
          uid: 346
        }, {
          uid: 347
        }]
      }, {
        uid: 159,
        c: 21,
        s: "LED1000",
        i: 39,
        v: [100, 200],
        ch: [{
          uid: 348,
          s: 17,
          n: 32
        }]
      }, {
        uid: 160,
        c: 21,
        s: "LUX1000",
        i: 33,
        v: [100, 200],
        ch: [{
          uid: 349
        }]
      }, {
        uid: 162,
        c: 21,
        s: "MOT0100",
        i: 146,
        v: [100, 200],
        ch: [{
          uid: 351
        }]
      }, {
        uid: 165,
        c: 21,
        s: "MOT0110",
        i: 141,
        v: [100, 200],
        ch: [{
          uid: 362
        }, {
          uid: 363
        }, {
          uid: 364
        }, {
          uid: 365,
          s: 112
        }, {
          uid: 366
        }]
      }, {
        uid: 166,
        c: 21,
        s: "MOT1100",
        i: 51,
        v: [200, 300],
        ch: [{
          uid: 367
        }]
      }, {
        uid: 167,
        c: 21,
        s: "MOT1101",
        i: 52,
        v: [100, 200],
        ch: [{
          uid: 368
        }, {
          uid: 369
        }, {
          uid: 370
        }, {
          uid: 371
        }]
      }, {
        uid: 168,
        c: 21,
        s: "MOT1102",
        i: 137,
        v: [200, 300],
        ch: [{
          uid: 372
        }, {
          uid: 373
        }, {
          uid: 374
        }, {
          uid: 375,
          s: 112
        }]
      }, {
        uid: 169,
        c: 21,
        s: "MOT1102",
        i: 140,
        v: [300, 400],
        ch: [{
          uid: 376
        }, {
          uid: 377
        }, {
          uid: 378
        }, {
          uid: 379,
          s: 112
        }]
      }, {
        uid: 178,
        c: 21,
        s: "OUT1000",
        i: 41,
        v: [100, 110],
        ch: [{
          uid: 394
        }]
      }, {
        uid: 179,
        c: 21,
        s: "OUT1000",
        i: 41,
        v: [110, 200],
        ch: [{
          uid: 395
        }]
      }, {
        uid: 180,
        c: 21,
        s: "OUT1001",
        i: 42,
        v: [100, 110],
        ch: [{
          uid: 396
        }]
      }, {
        uid: 181,
        c: 21,
        s: "OUT1001",
        i: 42,
        v: [110, 200],
        ch: [{
          uid: 397
        }]
      }, {
        uid: 182,
        c: 21,
        s: "OUT1002",
        i: 43,
        v: [100, 110],
        ch: [{
          uid: 398
        }]
      }, {
        uid: 183,
        c: 21,
        s: "OUT1002",
        i: 43,
        v: [110, 200],
        ch: [{
          uid: 399
        }]
      }, {
        uid: 184,
        c: 21,
        s: "OUT1100",
        i: 25,
        v: [100, 110],
        ch: [{
          uid: 400,
          s: 16,
          n: 4
        }]
      }, {
        uid: 185,
        c: 21,
        s: "OUT1100",
        i: 25,
        v: [110, 120],
        ch: [{
          uid: 401,
          s: 16,
          n: 4
        }]
      }, {
        uid: 186,
        c: 21,
        s: "OUT1100",
        i: 25,
        v: [120, 200],
        ch: [{
          uid: 402,
          s: 18,
          n: 4
        }]
      }, {
        uid: 187,
        c: 21,
        s: "PRE1000",
        i: 17,
        v: [100, 200],
        ch: [{
          uid: 403
        }]
      }, {
        uid: 189,
        c: 21,
        s: "RCC1000",
        i: 49,
        v: [100, 110],
        ch: [{
          uid: 405,
          n: 16
        }]
      }, {
        uid: 190,
        c: 21,
        s: "RCC1000",
        i: 49,
        v: [110, 200],
        ch: [{
          uid: 406,
          n: 16
        }]
      }, {
        uid: 191,
        c: 21,
        s: "RCC1000",
        i: 58,
        v: [200, 300],
        ch: [{
          uid: 407,
          n: 16
        }]
      }, {
        uid: 192,
        c: 21,
        s: "REL1000",
        i: 44,
        v: [100, 110],
        ch: [{
          uid: 408,
          n: 4
        }]
      }, {
        uid: 193,
        c: 21,
        s: "REL1000",
        i: 44,
        v: [110, 200],
        ch: [{
          uid: 409,
          n: 4
        }]
      }, {
        uid: 194,
        c: 21,
        s: "REL1100",
        i: 26,
        v: [100, 110],
        ch: [{
          uid: 410,
          s: 16,
          n: 4
        }]
      }, {
        uid: 195,
        c: 21,
        s: "REL1100",
        i: 26,
        v: [110, 120],
        ch: [{
          uid: 411,
          s: 16,
          n: 4
        }]
      }, {
        uid: 196,
        c: 21,
        s: "REL1100",
        i: 26,
        v: [120, 200],
        ch: [{
          uid: 412,
          s: 18,
          n: 4
        }]
      }, {
        uid: 197,
        c: 21,
        s: "REL1101",
        i: 27,
        v: [100, 110],
        ch: [{
          uid: 413,
          s: 16,
          n: 16
        }]
      }, {
        uid: 198,
        c: 21,
        s: "REL1101",
        i: 27,
        v: [110, 200],
        ch: [{
          uid: 414,
          s: 16,
          n: 16
        }]
      }, {
        uid: 199,
        c: 21,
        s: "REL1101",
        i: 130,
        v: [100, 300],
        ch: [{
          uid: 415,
          s: 18,
          n: 8
        }, {
          uid: 416,
          s: 16,
          n: 8
        }]
      }, {
        uid: 200,
        c: 21,
        s: "SAF1000",
        i: 38,
        v: [100, 110],
        ch: [{
          uid: 417
        }, {
          uid: 418
        }, {
          uid: 419
        }]
      }, {
        uid: 201,
        c: 21,
        s: "SAF1000",
        i: 38,
        v: [110, 200],
        ch: [{
          uid: 420
        }, {
          uid: 421
        }, {
          uid: 422
        }]
      }, {
        uid: 202,
        c: 21,
        s: "SND1000",
        i: 35,
        v: [100, 200],
        ch: [{
          uid: 423
        }]
      }, {
        uid: 205,
        c: 21,
        s: "STC1000",
        i: 48,
        v: [100, 110],
        ch: [{
          uid: 428
        }]
      }, {
        uid: 206,
        c: 21,
        s: "STC1000",
        i: 48,
        v: [110, 200],
        ch: [{
          uid: 429
        }]
      }, {
        uid: 207,
        c: 21,
        s: "STC1001",
        i: 69,
        v: [100, 110],
        ch: [{
          uid: 430
        }]
      }, {
        uid: 208,
        c: 21,
        s: "STC1001",
        i: 69,
        v: [110, 200],
        ch: [{
          uid: 431
        }]
      }, {
        uid: 209,
        c: 21,
        s: "STC1002",
        i: 71,
        v: [100, 110],
        ch: [{
          uid: 432
        }]
      }, {
        uid: 210,
        c: 21,
        s: "STC1002",
        i: 71,
        v: [110, 200],
        ch: [{
          uid: 433
        }]
      }, {
        uid: 211,
        c: 21,
        s: "STC1003",
        i: 72,
        v: [100, 110],
        ch: [{
          uid: 434
        }]
      }, {
        uid: 212,
        c: 21,
        s: "STC1003",
        i: 72,
        v: [110, 200],
        ch: [{
          uid: 435
        }]
      }, {
        uid: 213,
        c: 21,
        s: "STC1003",
        i: 142,
        v: [200, 300],
        ch: [{
          uid: 436
        }, {
          uid: 437
        }]
      }, {
        uid: 214,
        c: 21,
        s: "STC1005",
        i: 147,
        v: [100, 110],
        ch: [{
          uid: 438
        }, {
          uid: 439
        }]
      }, {
        uid: 215,
        c: 21,
        s: "STC1005",
        i: 147,
        v: [110, 200],
        ch: [{
          uid: 440
        }, {
          uid: 441
        }]
      }, {
        uid: 216,
        c: 21,
        s: "TMP1000",
        i: 19,
        v: [100, 200],
        ch: [{
          uid: 442
        }]
      }, {
        uid: 217,
        c: 21,
        s: "TMP1100",
        i: 55,
        v: [100, 200],
        ch: [{
          uid: 443,
          s: 33
        }, {
          uid: 444
        }, {
          uid: 445
        }]
      }, {
        uid: 218,
        c: 21,
        s: "TMP1101",
        i: 21,
        v: [100, 200],
        ch: [{
          uid: 446,
          s: 33,
          n: 4
        }, {
          uid: 447
        }, {
          uid: 448,
          n: 4
        }]
      }, {
        uid: 219,
        c: 21,
        s: "TMP1101",
        i: 143,
        v: [200, 300],
        ch: [{
          uid: 449,
          s: 33,
          n: 4
        }, {
          uid: 450
        }, {
          uid: 451,
          n: 4
        }]
      }, {
        uid: 220,
        c: 21,
        s: "TMP1200",
        i: 16,
        v: [100, 200],
        ch: [{
          uid: 452,
          s: 32
        }, {
          uid: 453
        }]
      }, {
        uid: 221,
        c: 21,
        s: "TMP1200",
        i: 78,
        v: [300, 400],
        ch: [{
          uid: 454,
          s: 32
        }, {
          uid: 455
        }]
      }, {
        uid: 222,
        c: 21,
        s: "TMP1202",
        i: 79,
        v: [100, 200],
        ch: [{
          uid: 456,
          s: 32
        }, {
          uid: 457
        }]
      }, {
        uid: 225,
        c: 21,
        s: "VCP1000",
        i: 53,
        v: [100, 200],
        ch: [{
          uid: 460
        }]
      }, {
        uid: 226,
        c: 21,
        s: "VCP1001",
        i: 31,
        v: [100, 110],
        ch: [{
          uid: 461
        }]
      }, {
        uid: 227,
        c: 21,
        s: "VCP1001",
        i: 31,
        v: [110, 200],
        ch: [{
          uid: 462
        }]
      }, {
        uid: 228,
        c: 21,
        s: "VCP1002",
        i: 30,
        v: [100, 110],
        ch: [{
          uid: 463
        }]
      }, {
        uid: 229,
        c: 21,
        s: "VCP1002",
        i: 30,
        v: [110, 200],
        ch: [{
          uid: 464
        }]
      }, {
        uid: 230,
        c: 21,
        s: "VCP1100",
        i: 64,
        v: [100, 200],
        ch: [{
          uid: 465
        }]
      }, {
        uid: 232,
        c: 21,
        s: " ",
        i: 4080,
        v: [0, 9999],
        ch: [{
          uid: 467
        }]
      }, {
        uid: 235,
        c: 21,
        s: "DIGITALINPUT_PORT",
        i: 1,
        v: [100, 200],
        ch: [{
          uid: 470
        }]
      }, {
        uid: 236,
        c: 21,
        s: "DIGITALOUTPUT_PORT",
        i: 2,
        v: [100, 110],
        ch: [{
          uid: 471,
          s: 16
        }]
      }, {
        uid: 237,
        c: 21,
        s: "DIGITALOUTPUT_PORT",
        i: 2,
        v: [110, 200],
        ch: [{
          uid: 472,
          s: 16
        }]
      }, {
        uid: 238,
        c: 21,
        s: "VOLTAGEINPUT_PORT",
        i: 3,
        v: [100, 110],
        ch: [{
          uid: 473,
          s: 48
        }]
      }, {
        uid: 239,
        c: 21,
        s: "VOLTAGEINPUT_PORT",
        i: 3,
        v: [110, 200],
        ch: [{
          uid: 474,
          s: 48
        }]
      }, {
        uid: 240,
        c: 21,
        s: "VOLTAGEINPUT_PORT",
        i: 3,
        v: [200, 300],
        ch: [{
          uid: 475,
          s: 48
        }]
      }, {
        uid: 241,
        c: 21,
        s: "VOLTAGERATIOINPUT_PORT",
        i: 4,
        v: [100, 200],
        ch: [{
          uid: 476,
          s: 64
        }]
      }, {
        uid: 242,
        c: 21,
        s: "VOLTAGERATIOINPUT_PORT",
        i: 4,
        v: [200, 300],
        ch: [{
          uid: 477,
          s: 64
        }]
      }, {
        uid: 247,
        c: 21,
        s: "FIRMWARE_UPGRADE_STM32F0",
        i: 4093,
        v: [100, 110],
        ch: [{
          uid: 482
        }]
      }, {
        uid: 248,
        c: 21,
        s: "FIRMWARE_UPGRADE_STM32F0",
        i: 4093,
        v: [400, 500],
        ch: [{
          uid: 483
        }]
      }, {
        uid: 249,
        c: 21,
        s: "FIRMWARE_UPGRADE_STM32F3",
        i: 4093,
        v: [120, 200],
        ch: [{
          uid: 484
        }]
      }, {
        uid: 252,
        c: 21,
        s: "FIRMWARE_UPGRADE_STM32G0",
        i: 4093,
        v: [110, 114],
        ch: [{
          uid: 487
        }]
      }, {
        uid: 253,
        c: 21,
        s: "FIRMWARE_UPGRADE_STM32G0",
        i: 4093,
        v: [114, 120],
        ch: [{
          uid: 488
        }]
      }, {
        uid: 255,
        c: 21,
        s: "FIRMWARE_UPGRADE_STM8S",
        i: 4094,
        v: [100, 200],
        ch: [{
          uid: 490
        }]
      }],
      USB: [{
        uid: 1,
        c: 16,
        s: "1000",
        i: 57,
        v: [200, 202],
        ch: [{
          uid: 1
        }]
      }, {
        uid: 2,
        c: 16,
        s: "1000",
        i: 57,
        v: [300, 313],
        ch: [{
          uid: 2
        }]
      }, {
        uid: 3,
        c: 16,
        s: "1000",
        i: 57,
        v: [313, 400],
        ch: [{
          uid: 3
        }]
      }, {
        uid: 4,
        c: 16,
        s: "1000",
        i: 33025,
        v: [200, 201],
        ch: [{
          uid: 4
        }]
      }, {
        uid: 5,
        c: 16,
        s: "1001",
        i: 56,
        v: [200, 202],
        ch: [{
          uid: 5,
          n: 4
        }]
      }, {
        uid: 6,
        c: 16,
        s: "1001",
        i: 56,
        v: [300, 313],
        ch: [{
          uid: 6,
          n: 4
        }]
      }, {
        uid: 7,
        c: 16,
        s: "1001",
        i: 56,
        v: [313, 400],
        ch: [{
          uid: 7,
          n: 4
        }]
      }, {
        uid: 8,
        c: 16,
        s: "1001",
        i: 33028,
        v: [200, 201],
        ch: [{
          uid: 8,
          n: 4
        }]
      }, {
        uid: 9,
        c: 3,
        s: "1002",
        i: 55,
        v: [100, 200],
        ch: [{
          uid: 9,
          n: 4
        }]
      }, {
        uid: 10,
        c: 1,
        s: "1008",
        i: 113,
        v: [0, 200],
        ch: [{
          uid: 10
        }]
      }, {
        uid: 11,
        c: 9,
        s: "1010/1018/1019",
        i: 69,
        v: [900, 1000],
        ch: [{
          uid: 11,
          s: 48,
          n: 8
        }, {
          uid: 12,
          s: 64,
          n: 8
        }, {
          uid: 13,
          n: 8
        }, {
          uid: 14,
          n: 8
        }]
      }, {
        uid: 12,
        c: 9,
        s: "1010/1018/1019",
        i: 69,
        v: [1000, 1100],
        ch: [{
          uid: 15,
          s: 48,
          n: 8
        }, {
          uid: 16,
          s: 64,
          n: 8
        }, {
          uid: 17,
          n: 8
        }, {
          uid: 18,
          n: 8
        }]
      }, {
        uid: 13,
        c: 9,
        s: "1011",
        i: 54,
        v: [0, 200],
        ch: [{
          uid: 19,
          s: 48,
          n: 2
        }, {
          uid: 20,
          s: 64,
          n: 2
        }, {
          uid: 21,
          n: 2
        }, {
          uid: 22,
          n: 2
        }]
      }, {
        uid: 14,
        c: 9,
        s: "1012",
        i: 68,
        v: [0, 601],
        ch: [{
          uid: 23,
          n: 16
        }, {
          uid: 24,
          n: 16
        }]
      }, {
        uid: 15,
        c: 9,
        s: "1012",
        i: 68,
        v: [601, 602],
        ch: [{
          uid: 25,
          n: 16
        }, {
          uid: 26,
          n: 16
        }]
      }, {
        uid: 16,
        c: 9,
        s: "1012",
        i: 68,
        v: [602, 700],
        ch: [{
          uid: 27,
          n: 16
        }, {
          uid: 28,
          n: 16
        }]
      }, {
        uid: 17,
        c: 9,
        s: "1013",
        i: 69,
        v: [0, 821],
        ch: [{
          uid: 29,
          s: 48,
          n: 8
        }, {
          uid: 30,
          s: 64,
          n: 8
        }, {
          uid: 31,
          n: 8
        }, {
          uid: 32,
          n: 8
        }]
      }, {
        uid: 18,
        c: 9,
        s: "1013/1018/1019",
        i: 69,
        v: [821, 900],
        ch: [{
          uid: 33,
          s: 48,
          n: 8
        }, {
          uid: 34,
          s: 64,
          n: 8
        }, {
          uid: 35,
          n: 8
        }, {
          uid: 36,
          n: 8
        }]
      }, {
        uid: 19,
        c: 9,
        s: "1014",
        i: 64,
        v: [0, 704],
        ch: [{
          uid: 37,
          n: 4
        }]
      }, {
        uid: 20,
        c: 9,
        s: "1014",
        i: 64,
        v: [704, 710],
        ch: [{
          uid: 38,
          n: 4
        }]
      }, {
        uid: 21,
        c: 9,
        s: "1014",
        i: 64,
        v: [710, 800],
        ch: [{
          uid: 39,
          n: 4
        }]
      }, {
        uid: 22,
        c: 9,
        s: "1014",
        i: 64,
        v: [800, 900],
        ch: [{
          uid: 40,
          n: 4
        }]
      }, {
        uid: 24,
        c: 9,
        s: "1015",
        i: 118,
        v: [0, 9999],
        ch: [{
          uid: 42
        }]
      }, {
        uid: 25,
        c: 9,
        s: "1016",
        i: 119,
        v: [0, 9999],
        ch: [{
          uid: 43
        }]
      }, {
        uid: 26,
        c: 9,
        s: "1017",
        i: 129,
        v: [0, 9999],
        ch: [{
          uid: 44,
          n: 8
        }]
      }, {
        uid: 27,
        c: 9,
        s: "1017",
        i: 135,
        v: [200, 300],
        ch: [{
          uid: 45,
          n: 8
        }]
      }, {
        uid: 29,
        c: 15,
        s: "1023",
        i: 48,
        v: [0, 104],
        ch: [{
          uid: 47
        }]
      }, {
        uid: 30,
        c: 15,
        s: "1023",
        i: 48,
        v: [104, 200],
        ch: [{
          uid: 48
        }]
      }, {
        uid: 31,
        c: 15,
        s: "1023",
        i: 49,
        v: [200, 201],
        ch: [{
          uid: 49
        }, {
          uid: 50
        }, {
          uid: 51
        }, {
          uid: 52
        }]
      }, {
        uid: 32,
        c: 15,
        s: "1023",
        i: 49,
        v: [201, 300],
        ch: [{
          uid: 53
        }, {
          uid: 54
        }, {
          uid: 55
        }, {
          uid: 56
        }]
      }, {
        uid: 33,
        c: 15,
        s: "1024",
        i: 52,
        v: [100, 200],
        ch: [{
          uid: 57
        }, {
          uid: 58
        }, {
          uid: 59
        }, {
          uid: 60
        }]
      }, {
        uid: 34,
        c: 15,
        s: "1024",
        i: 52,
        v: [300, 310],
        ch: [{
          uid: 61
        }, {
          uid: 62
        }, {
          uid: 63
        }, {
          uid: 64
        }]
      }, {
        uid: 35,
        c: 15,
        s: "1024",
        i: 52,
        v: [310, 320],
        ch: [{
          uid: 65
        }, {
          uid: 66
        }, {
          uid: 67
        }, {
          uid: 68
        }]
      }, {
        uid: 36,
        c: 15,
        s: "1024",
        i: 52,
        v: [320, 400],
        ch: [{
          uid: 69
        }, {
          uid: 70
        }, {
          uid: 71
        }, {
          uid: 72
        }]
      }, {
        uid: 40,
        c: 11,
        s: "1030",
        i: 74,
        v: [100, 300],
        ch: [{
          uid: 85,
          s: 17,
          n: 64
        }]
      }, {
        uid: 41,
        c: 11,
        s: "1031",
        i: 76,
        v: [100, 200],
        ch: [{
          uid: 86,
          s: 17,
          n: 64
        }]
      }, {
        uid: 42,
        c: 11,
        s: "1032",
        i: 76,
        v: [200, 300],
        ch: [{
          uid: 87,
          s: 17,
          n: 64
        }]
      }, {
        uid: 43,
        c: 7,
        s: "1040",
        i: 121,
        v: [0, 9999],
        ch: [{
          uid: 88
        }]
      }, {
        uid: 44,
        c: 17,
        s: "1041",
        i: 127,
        v: [200, 300],
        ch: [{
          uid: 89
        }]
      }, {
        uid: 45,
        c: 17,
        s: "1042",
        i: 51,
        v: [300, 400],
        ch: [{
          uid: 90
        }, {
          uid: 91
        }, {
          uid: 92
        }, {
          uid: 93
        }]
      }, {
        uid: 46,
        c: 17,
        s: "1043",
        i: 127,
        v: [300, 400],
        ch: [{
          uid: 94
        }]
      }, {
        uid: 47,
        c: 17,
        s: "1044",
        i: 51,
        v: [400, 500],
        ch: [{
          uid: 95
        }, {
          uid: 96
        }, {
          uid: 97
        }, {
          uid: 98
        }]
      }, {
        uid: 48,
        c: 17,
        s: "1044",
        i: 51,
        v: [500, 510],
        ch: [{
          uid: 99
        }, {
          uid: 100
        }, {
          uid: 101
        }, {
          uid: 102,
          s: 112
        }]
      }, {
        uid: 49,
        c: 17,
        s: "1044",
        i: 51,
        v: [510, 600],
        ch: [{
          uid: 103
        }, {
          uid: 104
        }, {
          uid: 105
        }, {
          uid: 106,
          s: 112
        }]
      }, {
        uid: 50,
        c: 19,
        s: "1045",
        i: 60,
        v: [100, 200],
        ch: [{
          uid: 107
        }, {
          uid: 108
        }]
      }, {
        uid: 51,
        c: 4,
        s: "1046",
        i: 59,
        v: [100, 102],
        ch: [{
          uid: 109,
          s: 65,
          n: 4
        }]
      }, {
        uid: 52,
        c: 4,
        s: "1046",
        i: 59,
        v: [102, 200],
        ch: [{
          uid: 110,
          s: 65,
          n: 4
        }]
      }, {
        uid: 53,
        c: 4,
        s: "1046",
        i: 59,
        v: [200, 300],
        ch: [{
          uid: 111,
          s: 65,
          n: 4
        }]
      }, {
        uid: 54,
        c: 5,
        s: "1047",
        i: 79,
        v: [100, 200],
        ch: [{
          uid: 112,
          n: 4
        }, {
          uid: 113,
          n: 4
        }]
      }, {
        uid: 55,
        c: 5,
        s: "1047",
        i: 79,
        v: [200, 300],
        ch: [{
          uid: 114,
          n: 4
        }, {
          uid: 115,
          n: 4
        }]
      }, {
        uid: 56,
        c: 5,
        s: "1047",
        i: 79,
        v: [300, 400],
        ch: [{
          uid: 116,
          n: 4
        }, {
          uid: 117,
          n: 4
        }]
      }, {
        uid: 57,
        c: 19,
        s: "1048",
        i: 50,
        v: [100, 200],
        ch: [{
          uid: 118,
          s: 33,
          n: 4
        }, {
          uid: 119
        }, {
          uid: 120,
          n: 4
        }]
      }, {
        uid: 58,
        c: 19,
        s: "1048",
        i: 50,
        v: [200, 300],
        ch: [{
          uid: 121,
          s: 33,
          n: 4
        }, {
          uid: 122
        }, {
          uid: 123,
          n: 4
        }]
      }, {
        uid: 59,
        c: 17,
        s: "1049",
        i: 127,
        v: [0, 200],
        ch: [{
          uid: 124
        }]
      }, {
        uid: 60,
        c: 19,
        s: "1051",
        i: 112,
        v: [0, 200],
        ch: [{
          uid: 125,
          s: 33
        }, {
          uid: 126
        }]
      }, {
        uid: 61,
        c: 19,
        s: "1051",
        i: 112,
        v: [200, 300],
        ch: [{
          uid: 127,
          s: 33
        }, {
          uid: 128
        }, {
          uid: 129
        }]
      }, {
        uid: 62,
        c: 19,
        s: "1051",
        i: 112,
        v: [300, 400],
        ch: [{
          uid: 130,
          s: 33
        }, {
          uid: 131
        }, {
          uid: 132
        }]
      }, {
        uid: 63,
        c: 19,
        s: "1051",
        i: 112,
        v: [400, 500],
        ch: [{
          uid: 133,
          s: 33
        }, {
          uid: 134
        }, {
          uid: 135
        }]
      }, {
        uid: 64,
        c: 5,
        s: "1052",
        i: 75,
        v: [0, 101],
        ch: [{
          uid: 136
        }, {
          uid: 137
        }]
      }, {
        uid: 65,
        c: 5,
        s: "1052",
        i: 75,
        v: [101, 110],
        ch: [{
          uid: 138
        }, {
          uid: 139
        }]
      }, {
        uid: 66,
        c: 5,
        s: "1052",
        i: 75,
        v: [110, 300],
        ch: [{
          uid: 140
        }, {
          uid: 141
        }]
      }, {
        uid: 67,
        c: 1,
        s: "1053",
        i: 113,
        v: [300, 400],
        ch: [{
          uid: 142
        }]
      }, {
        uid: 68,
        c: 6,
        s: "1054",
        i: 53,
        v: [0, 200],
        ch: [{
          uid: 143,
          n: 2
        }]
      }, {
        uid: 69,
        c: 10,
        s: "1055",
        i: 77,
        v: [100, 200],
        ch: [{
          uid: 144
        }]
      }, {
        uid: 70,
        c: 17,
        s: "1056",
        i: 51,
        v: [0, 200],
        ch: [{
          uid: 145
        }, {
          uid: 146
        }, {
          uid: 147
        }, {
          uid: 148
        }]
      }, {
        uid: 71,
        c: 17,
        s: "1056",
        i: 51,
        v: [200, 300],
        ch: [{
          uid: 149
        }, {
          uid: 150
        }, {
          uid: 151
        }, {
          uid: 152
        }]
      }, {
        uid: 72,
        c: 5,
        s: "1057",
        i: 128,
        v: [300, 400],
        ch: [{
          uid: 153
        }]
      }, {
        uid: 73,
        c: 5,
        s: "1057",
        i: 128,
        v: [400, 500],
        ch: [{
          uid: 154
        }]
      }, {
        uid: 74,
        c: 14,
        s: "1058",
        i: 116,
        v: [100, 200],
        ch: [{
          uid: 155
        }, {
          uid: 156
        }]
      }, {
        uid: 75,
        c: 1,
        s: "1059",
        i: 126,
        v: [400, 500],
        ch: [{
          uid: 157
        }]
      }, {
        uid: 76,
        c: 13,
        s: "1060",
        i: 88,
        v: [100, 200],
        ch: [{
          uid: 158,
          n: 2
        }, {
          uid: 159,
          n: 4
        }]
      }, {
        uid: 77,
        c: 2,
        s: "1061",
        i: 58,
        v: [100, 200],
        ch: [{
          uid: 160,
          n: 8
        }, {
          uid: 161,
          n: 8
        }]
      }, {
        uid: 78,
        c: 2,
        s: "1061",
        i: 58,
        v: [200, 300],
        ch: [{
          uid: 162,
          n: 8
        }, {
          uid: 163,
          n: 8
        }]
      }, {
        uid: 79,
        c: 2,
        s: "1061",
        i: 58,
        v: [300, 400],
        ch: [{
          uid: 164,
          n: 8
        }, {
          uid: 165,
          n: 8
        }]
      }, {
        uid: 80,
        c: 18,
        s: "1062",
        i: 122,
        v: [100, 200],
        ch: [{
          uid: 166,
          n: 4
        }]
      }, {
        uid: 81,
        c: 18,
        s: "1063",
        i: 123,
        v: [100, 200],
        ch: [{
          uid: 167
        }, {
          uid: 168,
          n: 4
        }, {
          uid: 169
        }]
      }, {
        uid: 82,
        c: 13,
        s: "1064",
        i: 89,
        v: [100, 200],
        ch: [{
          uid: 170,
          n: 2
        }, {
          uid: 171,
          n: 2
        }]
      }, {
        uid: 83,
        c: 13,
        s: "1065",
        i: 62,
        v: [100, 200],
        ch: [{
          uid: 172
        }, {
          uid: 173,
          n: 2
        }, {
          uid: 174
        }, {
          uid: 175,
          s: 48,
          n: 2
        }, {
          uid: 176
        }, {
          uid: 177,
          s: 64,
          n: 2
        }, {
          uid: 178
        }]
      }, {
        uid: 84,
        c: 2,
        s: "1066",
        i: 130,
        v: [100, 200],
        ch: [{
          uid: 179
        }, {
          uid: 180
        }]
      }, {
        uid: 85,
        c: 18,
        s: "1067",
        i: 123,
        v: [200, 300],
        ch: [{
          uid: 181
        }]
      }, {
        uid: 86,
        c: 9,
        s: "1202/1203",
        i: 125,
        v: [0, 120],
        ch: [{
          uid: 182,
          s: 48,
          n: 8
        }, {
          uid: 183,
          s: 64,
          n: 8
        }, {
          uid: 184,
          n: 8
        }, {
          uid: 185,
          n: 8
        }]
      }, {
        uid: 87,
        c: 20,
        s: "1202/1203",
        i: 125,
        v: [0, 200],
        n: 1,
        ch: [{
          uid: 186,
          s: 81
        }]
      }, {
        uid: 88,
        c: 9,
        s: "1202/1203",
        i: 125,
        v: [120, 200],
        ch: [{
          uid: 187,
          s: 48,
          n: 8
        }, {
          uid: 188,
          s: 64,
          n: 8
        }, {
          uid: 189,
          n: 8
        }, {
          uid: 190,
          n: 8
        }]
      }, {
        uid: 89,
        c: 9,
        s: "1202/1203",
        i: 125,
        v: [200, 300],
        ch: [{
          uid: 191,
          s: 48,
          n: 8
        }, {
          uid: 192,
          s: 64,
          n: 8
        }, {
          uid: 193,
          n: 8
        }, {
          uid: 194,
          n: 8
        }]
      }, {
        uid: 90,
        c: 20,
        s: "1202/1203",
        i: 125,
        v: [200, 9999],
        n: 1,
        ch: [{
          uid: 195,
          s: 81
        }]
      }, {
        uid: 91,
        c: 20,
        s: "1204",
        i: 61,
        v: [0, 9999],
        ch: [{
          uid: 196,
          s: 81,
          n: 2
        }]
      }, {
        uid: 92,
        c: 20,
        s: "1215/1216/1217/1218",
        i: 82,
        v: [0, 9999],
        ch: [{
          uid: 197,
          s: 81
        }]
      }, {
        uid: 93,
        c: 20,
        s: "1219/1220/1221/1222",
        i: 83,
        v: [0, 9999],
        ch: [{
          uid: 198,
          s: 81
        }, {
          uid: 199,
          n: 8
        }, {
          uid: 200,
          n: 8
        }]
      }, {
        uid: 94,
        c: 25,
        s: "ADP0001",
        i: 134,
        v: [200, 300],
        ch: [{
          uid: 201
        }, {
          uid: 202,
          n: 2
        }, {
          uid: 203,
          n: 2
        }]
      }, {
        uid: 96,
        c: 25,
        s: "ADP0002",
        i: 160,
        v: [100, 200],
        ch: [{
          uid: 207
        }, {
          uid: 208,
          n: 2
        }, {
          uid: 209,
          n: 2
        }]
      }, {
        uid: 141,
        c: 8,
        s: "HUB0000",
        i: 63,
        v: [100, 200],
        ch: [{
          uid: 326
        }]
      }, {
        uid: 142,
        c: 8,
        s: "HUB0000",
        i: 63,
        v: [300, 400],
        ch: [{
          uid: 327
        }]
      }, {
        uid: 143,
        c: 8,
        s: "HUB0000",
        i: 63,
        v: [400, 500],
        ch: [{
          uid: 328
        }]
      }, {
        uid: 144,
        c: 8,
        s: "HUB0001",
        i: 67,
        v: [100, 115],
        ch: [{
          uid: 329
        }]
      }, {
        uid: 145,
        c: 8,
        s: "HUB0001",
        i: 67,
        v: [115, 200],
        ch: [{
          uid: 330
        }]
      }, {
        uid: 146,
        c: 8,
        s: "HUB0002",
        i: 70,
        v: [100, 200],
        ch: [{
          uid: 331
        }]
      }, {
        uid: 149,
        c: 8,
        s: "HUB0007",
        i: 71,
        v: [100, 200],
        ch: [{
          uid: 334
        }]
      }, {
        uid: 150,
        c: 8,
        s: "HUB5000",
        i: 66,
        v: [100, 200],
        ch: [{
          uid: 335
        }]
      }, {
        uid: 151,
        c: 8,
        s: "HUB5000",
        i: 66,
        v: [200, 300],
        ch: [{
          uid: 336
        }]
      }, {
        uid: 157,
        c: 12,
        s: "LED0100",
        i: 161,
        v: [100, 200],
        ch: [{
          uid: 344
        }, {
          uid: 345
        }]
      }, {
        uid: 161,
        c: 1,
        s: "MOT0100",
        i: 146,
        v: [100, 200],
        ch: [{
          uid: 350
        }]
      }, {
        uid: 163,
        c: 17,
        s: "MOT0109",
        i: 140,
        v: [100, 200],
        ch: [{
          uid: 352
        }, {
          uid: 353
        }, {
          uid: 354
        }, {
          uid: 355,
          s: 112
        }, {
          uid: 356
        }]
      }, {
        uid: 164,
        c: 17,
        s: "MOT0110",
        i: 141,
        v: [100, 200],
        ch: [{
          uid: 357
        }, {
          uid: 358
        }, {
          uid: 359
        }, {
          uid: 360,
          s: 112
        }, {
          uid: 361
        }]
      }, {
        uid: 188,
        c: 2,
        s: "RCC0004",
        i: 58,
        v: [400, 500],
        ch: [{
          uid: 404,
          n: 8
        }]
      }, {
        uid: 231,
        c: 22,
        s: " ",
        i: 175,
        v: [0, 9999],
        ch: [{
          uid: 466
        }]
      }, {
        uid: 243,
        c: 1,
        s: "1054",
        i: 113,
        v: [200, 300],
        ch: [{
          uid: 478
        }]
      }, {
        uid: 245,
        c: 23,
        s: "FIRMWARE_UPGRADE_M3",
        i: 152,
        v: [0, 9999],
        ch: [{
          uid: 480
        }]
      }, {
        uid: 246,
        c: 23,
        s: "FIRMWARE_UPGRADE_STM32_USB",
        i: 156,
        v: [100, 200],
        ch: [{
          uid: 481
        }]
      }, {
        uid: 250,
        c: 23,
        s: "FIRMWARE_UPGRADE_STM32Fv2_USB",
        i: 156,
        v: [400, 500],
        ch: [{
          uid: 485
        }]
      }, {
        uid: 251,
        c: 23,
        s: "FIRMWARE_UPGRADE_STM32G_USB",
        i: 156,
        v: [200, 300],
        ch: [{
          uid: 486
        }]
      }, {
        uid: 254,
        c: 23,
        s: "FIRMWARE_UPGRADE_STM32L_USB",
        i: 156,
        v: [300, 400],
        ch: [{
          uid: 489
        }]
      }, {
        uid: 259,
        c: 9,
        s: "ifkit488",
        i: 33281,
        v: [0, 101],
        ch: [{
          uid: 494,
          s: 64,
          n: 4
        }, {
          uid: 495,
          n: 8
        }, {
          uid: 496,
          n: 8
        }]
      }],
      SPI: [{
        uid: 147,
        c: 8,
        s: "HUB0004",
        i: 1,
        v: [100, 200],
        ch: [{
          uid: 332
        }]
      }, {
        uid: 148,
        c: 8,
        s: "HUB0004",
        i: 1,
        v: [200, 300],
        ch: [{
          uid: 333
        }]
      }, {
        uid: 233,
        c: 22,
        s: " ",
        i: 65535,
        v: [0, 9999],
        ch: [{
          uid: 468
        }]
      }, {
        uid: 244,
        c: 23,
        s: "FIRMWARE_UPGRADE_M3",
        i: 2,
        v: [0, 9999],
        ch: [{
          uid: 479
        }]
      }],
      VIRTUAL: [{
        uid: 234,
        c: 24,
        s: "Dictionary",
        i: 0,
        v: [100, 200],
        ch: [{
          uid: 469
        }]
      }]
    };

    function findPhidgetUniqueDevice(data) {
      const typeDevs = PhidgetDevices[data.type];
      for (const d of typeDevs) {
        if (d.v[0] > data.version || d.v[1] <= data.version) continue;
        if (data.type === 'VINT') {
          if (d.i !== data.vintID) continue;
        } else {
          if (d.i !== data.productID) continue;
          if (data.type === 'USB' && (d.n ?? 0) !== data.interfaceNum) continue;
        }
        return d;
      }
      throw new PhidgetError(exports.ErrorCode.UNEXPECTED, "Couldn't find device in device list!!");
    }
    /** @internal */
    class Device {
      conn;
      devDef;
      version;
      label;
      serialNumber;
      fwstr;
      id;
      parent;
      get parentId() {
        return this.parent?.id ?? '0';
      }
      vintDeviceProps;
      hubPortProps;
      get vintID() {
        return this.devDef.i;
      }
      get sku() {
        return this.devDef.s;
      }
      get class() {
        return this.devDef.c;
      }
      get hubPort() {
        return this.vintDeviceProps?.hubPort ?? 0;
      }
      get isHubPort() {
        return this.vintDeviceProps?.isHubPort ?? false;
      }
      get index() {
        return this.vintDeviceProps?.uniqueIndex ?? 0;
      }
      constructor(conn, data) {
        this.conn = conn;
        this.devDef = data.devDef;
        this.version = data.version;
        this.label = data.label;
        this.serialNumber = data.serialNumber;
        this.fwstr = data.fwstr;
        this.id = data.id;
        this.parent = data.parent;
        if (data.type === 'VINT') this.vintDeviceProps = data.vintDeviceProps;
        if (data.type === 'HUB') this.hubPortProps = data.hubPortProps;
      }
      toString() {
        if (this.class === exports.DeviceClass.VINT) {
          return this.sku + ' (' + this.name + ') v' + this.version + ' -> ' + this.parent.sku + ' Port:' + this.hubPort + ' Serial#:' + this.serialNumber + (this.conn._isRemote ? " NET" : " USB");
        }
        return this.sku + ' (' + this.name + ') v' + this.version + ' Serial#:' + this.serialNumber + (this.conn._isRemote ? " NET" : " USB");
      }
    }

    /** @internal */
    class NetworkDevice extends Device {
      deviceID;
      name;
      constructor(conn, data) {
        super(conn, data);
        this.deviceID = data.deviceID;
        this.name = data.name;
      }
      findPhidgetUniqueChannel(uniqueIndex) {
        let index = 0;
        for (const c of this.devDef.ch) {
          if (uniqueIndex < index + (c.n ?? 1)) return c;
          index += c.n ?? 1;
        }
        throw new PhidgetError(exports.ErrorCode.UNEXPECTED, "Couldn't find channel in channel list!!");
      }
    }

    const NET_MAJOR = 2;
    const NET_MINOR = 4;
    const NET_IDENT = "phidgetclient";
    /** @public */
    class NetworkConnectionBase extends PhidgetConnection {
      /** @internal */
      _hostname;
      /** @internal */
      _port;
      /** @internal */
      _protocol;
      /** @internal */
      _uri;
      /** @internal */
      _generation;
      /** @internal */
      _timeout;
      /** @internal */
      _nonceC;
      /** @internal */
      _passwd;
      /** @internal */
      _reqseq;
      /** @internal */
      _requests;
      /** @internal */
      _handleAbandonedRequestsInterval;
      /** @internal */
      _connectionMaintainer;
      /** @internal */
      _keepAliveTimeout;
      /** @internal */
      _onauthdata;
      /** @internal */
      _type;
      /** @internal */
      _opened;
      /** @internal */
      _resolveConnect;
      onAuthenticationNeeded;
      onConnect;
      onDisconnect;
      constructor(optsOrUriOrPort, optsOrHostname, opts) {
        let options = {};
        let uri = '';
        let hostname = '';
        let port = 0;
        if (optsOrUriOrPort != undefined && typeof optsOrUriOrPort === 'object') {
          options = optsOrUriOrPort;
        } else if (optsOrUriOrPort != undefined && typeof optsOrUriOrPort === 'string') {
          uri = optsOrUriOrPort;
          if (optsOrHostname != undefined && typeof optsOrHostname === 'object') options = optsOrHostname;
        } else if (optsOrUriOrPort != undefined && typeof optsOrUriOrPort === 'number') {
          port = optsOrUriOrPort;
          if (optsOrHostname != undefined && typeof optsOrHostname === 'string') {
            hostname = optsOrHostname;
            if (opts != undefined && typeof opts === 'object') options = opts;
          }
        }
        if (!options.name) options.name = uri;
        super(options);
        this._type = 1;
        this._generation = 0;
        this._timeout = 8000;
        this._reqseq = 10;
        this._requests = new Map();
        this._opened = false;
        this._uri = uri;
        if (options.hostname && hostname === '') {
          if (typeof options.hostname === 'string') hostname = options.hostname;
        }
        if (hostname === '') hostname = 'localhost';
        this._hostname = hostname;
        if (options.port && port === 0) {
          if (typeof options.port === 'number') port = options.port;
          if (typeof options.port === 'string') port = Number(options.port);
        }
        this._port = port;
        if (options.onConnect && typeof options.onConnect === 'function') this.onConnect = options.onConnect;else this.onConnect = null;
        if (options.onDisconnect && typeof options.onDisconnect === 'function') this.onDisconnect = options.onDisconnect;else this.onDisconnect = null;
        if (options.onAuthenticationNeeded && typeof options.onAuthenticationNeeded === 'function') this.onAuthenticationNeeded = options.onAuthenticationNeeded;else this.onAuthenticationNeeded = null;
        if (options.passwd) this._passwd = options.passwd;else this._passwd = '';
        this._handleAbandonedRequestsInterval = setInterval(this._handleAbandonedRequests.bind(this), 2000);
      }
      delete() {
        if (this._handleAbandonedRequestsInterval != undefined) {
          clearInterval(this._handleAbandonedRequestsInterval);
          delete this._handleAbandonedRequestsInterval;
        }
        super.delete();
      }
      setKeepAlive(timeout) {
        if (typeof timeout !== 'number' || isNaN(timeout)) throw 'invalid keep alive:' + timeout;
        this._timeout = timeout;
      }
      close() {
        logdebug("Network Connection close() called");
        this._opened = false;
        if (this._connectionMaintainer != undefined) clearTimeout(this._connectionMaintainer);
        delete this._connectionMaintainer;
        this._detachAllDevices();
        this._closesocket();
      }
      /** @internal */
      _onmessage(msg, req) {
        let json;
        if (msg !== undefined) {
          const tmp1 = msg.replace(/("[OI]"|"phid"|"chid"|"parent"):([0-9]+)/g, "$1:\"$2\"");
          const tmp2 = tmp1.replace(/([:[,])[-+]?nan(\([\w]*\))?/ig, "$1\"**NAN**\"");
          if (tmp1 !== tmp2) {
            json = _JSON$parse(tmp2, (key, value) => {
              if (key == 'v') {
                if (value === "**NAN**") return NaN;
                if (Array.isArray(value)) return value.map(val => {
                  if (val === "**NAN**") return NaN;
                  return val;
                });
              }
              return value;
            });
          } else {
            json = _JSON$parse(tmp2);
          }
        }
        try {
          if (this.connected) this._ondatamessage(json, req);else this._onauthmessage(json);
        } catch (err) {
          if (this.onError && err instanceof PhidgetError) {
            try {
              this.onError(err.errorCode, err.message);
            } catch (err) {
              logEventException(err);
            }
            loginfo("Error handling message from server", err);
          } else {
            logerr("Error handling message from server", err);
          }
        }
      }
      /** @internal */
      _handleAbandonedRequests() {
        for (const r of this._requests.entries()) {
          if (r[1].generation != this._generation) {
            r[1].onError(exports.ErrorCode.CONNECTION_RESET, "Connection Reset");
            this._requests.delete(r[0]);
            continue;
          }
          if (tm() - r[1].time > 5000) {
            r[1].onTimeout();
            this._requests.delete(r[0]);
          }
        }
      }
      /** @internal */
      _getNextRequestSequence() {
        if (this._reqseq >= 65535) this._reqseq = 10;
        this._reqseq++;
        return this._reqseq;
      }
      /** @internal */
      _sendRequest(flags, reqseq, repseq, type, stype, data) {
        if (reqseq === 0) reqseq = this._getNextRequestSequence();
        return new Promise((resolve, reject) => {
          this._requests.set(reqseq, {
            generation: this._generation,
            time: tm(),
            onReply: function (res) {
              if ('E' in res) {
                if (res.E !== exports.ErrorCode.SUCCESS) {
                  if (res.R != undefined) reject(new PhidgetError(res.E, res.R));
                  reject(new PhidgetError(res.E));
                } else {
                  if (res.R != undefined) resolve(res.R);
                  if (res.D != undefined) {
                    const binaryString = atob(res.D);
                    const uint8Array = Uint8Array.from(binaryString, char => char.charCodeAt(0));
                    resolve(uint8Array);
                  }
                  resolve();
                }
              } else {
                resolve(res);
              }
            },
            onTimeout: function () {
              reject(new PhidgetError(exports.ErrorCode.TIMEOUT));
            },
            onError: function (code, msg) {
              reject(new PhidgetError(code, msg));
            }
          });
          const json = _JSON$stringify(data);
          const data2 = json.replace(/("[OI]"|"phid"|"channel"):"([0-9]+)"/g, "$1:$2");
          const req = new Request(data2.length, flags, reqseq, repseq, type, stype);
          this._send(req, data2);
        });
      }
      /** @internal */
      _sendReply(repseq, type, stype, reply) {
        const NRF_REPLY = 0x0002;
        const reqseq = this._getNextRequestSequence();
        let data = '';
        if (reply != undefined) data = _JSON$stringify(reply);
        const req = new Request(data.length, NRF_REPLY, reqseq, repseq, type, stype);
        this._send(req, data);
      }
      /** @internal */
      _maintainConnection() {
        logdebug("Maintaining network connection..");
        const nextMaintainer = () => {
          if (!this._connectionMaintainer && this._opened) {
            logdebug(".. Check again in 4 seconds.");
            this._connectionMaintainer = setTimeout(this._maintainConnection.bind(this), 4000);
          }
        };
        if (this._connectionMaintainer) delete this._connectionMaintainer;
        if (this.connected) {
          logdebug(".. already connected ..");
          nextMaintainer();
        } else {
          logdebug(".. trying to connect ..");
          this.connect().then(() => {
            logdebug(".. connected!");
            nextMaintainer();
          }).catch(err => {
            if (this.onError && err instanceof PhidgetError) {
              try {
                this.onError(err.errorCode, err.message);
              } catch (err) {
                logEventException(err);
              }
            }
            logerr("Error connecting", err);
            logdebug(".. failed to connect! ..");
            nextMaintainer();
          });
        }
      }
      /** @internal */
      _doclose() {
        this._detachAllDevices();
        this._closesocket();
      }
      /** @internal */
      _onauthmessage(data) {
        if (this._onauthdata == undefined) throw new Error('packet recieved while not connected and authdata is not defined');
        this._onauthdata(data);
      }
      /** @internal */
      _ondatamessage(data, req) {
        const request = this._requests.get(req.repseq);
        if (request) {
          this._requests.delete(req.repseq);
          request.onReply(data);
        }
        if (req.flgs & 2) {
          if (request === undefined) throw new PhidgetError(exports.ErrorCode.UNEXPECTED, 'No handler registered for reply: ' + req);
          return;
        }
        switch (req.type) {
          case 20:
            this._handleCommand(req);
            break;
          case 30:
            this._handleDevice(req, data);
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.INVALID, 'Unknown request type:' + req.type);
        }
      }
      /** @internal */
      _handleCommand(req) {
        switch (req.stype) {
          case 41:
            logdebug("Got a keepalive message");
            if (this._keepAliveTimeout != undefined) {
              logdebug("Cleaning previous keepalive timeout");
              clearTimeout(this._keepAliveTimeout);
            }
            this._keepAliveTimeout = setTimeout(() => {
              logdebug("Keepalive timeout passed");
              delete this._keepAliveTimeout;
              if (this.connected) {
                if (this.onError) {
                  try {
                    this.onError(exports.ErrorCode.KEEP_ALIVE, "KeepAlive timeout. Closing connection to server.");
                  } catch (err) {
                    logEventException(err);
                  }
                }
                logerr("KeepAlive timeout. Closing connection to server.");
                this._doclose();
              }
            }, this._timeout);
            this._sendReply(req.reqseq, 20, 41);
            return;
          default:
            throw new PhidgetError(exports.ErrorCode.UNEXPECTED, 'Unknown command subrequest:' + req.stype);
        }
      }
      /** @internal */
      _handleDevice(req, data) {
        switch (req.stype) {
          case 50:
            this._handleDeviceAttach(data);
            return;
          case 55:
            this._handleDeviceDetach(data);
            return;
          case 70:
            this._handleBridgePacket(req, data);
            return;
          case 80:
            this._handleChannel(data);
            return;
          default:
            throw new PhidgetError(exports.ErrorCode.UNEXPECTED, 'Unknown device subrequest:' + req.stype);
        }
      }
      /** @internal */
      _handleDeviceAttach(data) {
        const devDef = findPhidgetUniqueDevice(data);
        let devData;
        const baseData = {
          version: data.version,
          label: data.label,
          serialNumber: data.serialNumber,
          devDef: devDef,
          fwstr: data.fwstr ?? devDef.s,
          id: data.phid,
          parent: this._getDevice(data.parent) ?? undefined,
          deviceID: data.deviceID,
          name: data.name
        };
        if (data.type === 'VINT') {
          devData = {
            ...baseData,
            type: 'VINT',
            vintDeviceProps: {
              vintProto: data.vintProto ?? 1,
              suppSetSpeed: data.suppSetSpeed ? !!data.suppSetSpeed : false,
              suppAutoSetSpeed: data.suppSetSpeed ? !!data.suppSetSpeed : false,
              maxSpeed: data.maxSpeed ?? 4294967295,
              commSpeed: data.commSpeed ?? 4294967295,
              hubPort: data.hubPort,
              isHubPort: !!data.isHubPort,
              uniqueIndex: data.index
            }
          };
        } else if (devDef.c === exports.DeviceClass.HUB) {
          let hubPortCnt;
          if (data.hubPortsInfo) hubPortCnt = data.hubPortsInfo.portProto.length;else hubPortCnt = data.deviceID === exports.DeviceID.PN_HUB0007 ? 1 : 6;
          const hubPortProps = [];
          for (let i = 0; i < hubPortCnt; i++) {
            if (data.hubPortsInfo) {
              hubPortProps.push({
                portProto: data.hubPortsInfo.portProto[i],
                portSuppSetSpeed: !!data.hubPortsInfo.portSuppSetSpeed[i],
                portSuppAutoSetSpeed: !!data.hubPortsInfo.portSuppSetSpeed[i],
                portMaxSpeed: data.hubPortsInfo.portMaxSpeed[i]
              });
            } else {
              hubPortProps.push({
                portProto: 1,
                portSuppSetSpeed: false,
                portSuppAutoSetSpeed: false,
                portMaxSpeed: 100000
              });
            }
          }
          devData = {
            ...baseData,
            type: 'HUB',
            hubPortProps: hubPortProps
          };
        } else {
          devData = {
            ...baseData,
            type: 'OTHER'
          };
        }
        const dev = new NetworkDevice(this, devData);
        this._deviceAttach(dev);
      }
      /** @internal */
      _handleDeviceDetach(data) {
        const dev = this._getDevice(data.phid);
        if (dev) this._deviceDetach(dev);
      }
      /** @internal */
      _handleChannel(data) {
        const dev = this._devices.get(data.parent);
        if (!dev) throw new PhidgetError(exports.ErrorCode.UNEXPECTED, 'missing channel parent');
        const chDef = dev.findPhidgetUniqueChannel(data.uniqueIndex);
        const chData = {
          id: data.chid,
          chDef: chDef,
          uniqueIndex: data.uniqueIndex,
          index: data.index,
          cpversion: data.version,
          name: data.name,
          class: data.class
        };
        const ch = new NetworkChannel(this, dev, chData);
        this._channelAttach(ch);
      }
      /** @internal */
      _handleBridgePacket(req, data) {
        const bp = new BridgePacket(this, data);
        let reply;
        try {
          bp.deliver();
        } catch (err) {
          if (err instanceof PhidgetError) {
            reply = {
              E: err.errorCode,
              R: err.message
            };
          } else {
            reply = {
              E: exports.ErrorCode.UNEXPECTED,
              R: '' + err
            };
          }
        }
        if (!bp.isEvent()) this._sendReply(req.reqseq, req.type, req.stype, reply);
      }
      /** @internal */
      _handshake() {
        return new Promise((resolve, reject) => {
          const pkt = {
            type: this._protocol,
            pmajor: NET_MAJOR,
            pminor: NET_MINOR
          };
          const json = _JSON$stringify(pkt);
          const req = new Request(json.length, 0, 0, 0, 10, 10);
          this._send(req, json);
          this._onauthdata = HandShakeS0;
          function HandShakeS0(data) {
            if (data.result !== exports.ErrorCode.SUCCESS) {
              reject(new PhidgetError(data.result, 'server rejected handshake'));
              return;
            }
            this._nonceC = this._createSalt(16);
            const pkt = {
              ident: NET_IDENT,
              nonceC: this._nonceC
            };
            const json = _JSON$stringify(pkt);
            const req = new Request(json.length, 0, 0, 0, 10, 30);
            try {
              this._send(req, json);
            } catch (err) {
              reject(err);
              return;
            }
            this._onauthdata = AuthS0;
          }
          function AuthS0(data) {
            if (data.result !== exports.ErrorCode.SUCCESS) {
              reject(new PhidgetError(data.result, 'authentication failed'));
              return;
            }
            if (this._nonceC != data.nonceC) {
              reject(new PhidgetError(exports.ErrorCode.UNEXPECTED, 'Authentication Failure: nonce do not match (' + this._nonceC + ') vs (' + data.nonceC + ')'));
              return;
            }
            const challenge = NET_IDENT + this._passwd + this._nonceC + data.nonceS + data.salt;
            const proof = this._hash(challenge);
            const pkt = {
              nonceC: this._nonceC,
              nonceS: data.nonceS,
              proof: proof
            };
            const json = _JSON$stringify(pkt);
            const req = new Request(json.length, 0, 0, 0, 10, 32);
            try {
              this._send(req, json);
            } catch (err) {
              reject(err);
              return;
            }
            this._onauthdata = AuthReply;
          }
          function AuthReply(data) {
            delete this._onauthdata;
            if (data.E != exports.ErrorCode.SUCCESS) {
              if (this.onAuthenticationNeeded) {
                let pass;
                try {
                  pass = this.onAuthenticationNeeded();
                } catch (err) {
                  logEventException(err);
                }
                if (pass != undefined && typeof pass === 'string') {
                  this._passwd = pass;
                  setTimeout(() => {
                    this.connect().then(() => resolve()).catch(err => reject(err));
                  }, 10);
                  return;
                }
              } else {
                logwarn("A password is required for this server. Handle the onAuthenticationNeeded event to return a password.");
              }
              reject(new PhidgetError(data.E, 'authentication failed: server rejected proof'));
              return;
            }
            this.connected = true;
            if (this.onConnect) {
              try {
                this.onConnect();
              } catch (err) {
                logEventException(err);
              }
            }
            if (this._connectionMaintainer != undefined) clearTimeout(this._connectionMaintainer);
            delete this._connectionMaintainer;
            this._maintainConnection();
            resolve();
          }
        });
      }
    }
    function DecodeUTF8(bytes) {
      let s = '';
      let i = 0;
      while (i < bytes.length) {
        let c = bytes[i++];
        if (c > 127) {
          if (c > 191 && c < 224) {
            if (i >= bytes.length) throw 'UTF-8 decode: incomplete 2-byte sequence';
            c = (c & 31) << 6 | bytes[i] & 63;
          } else if (c > 223 && c < 240) {
            if (i + 1 >= bytes.length) throw 'UTF-8 decode: incomplete 3-byte sequence';
            c = (c & 15) << 12 | (bytes[i] & 63) << 6 | bytes[++i] & 63;
          } else if (c > 239 && c < 248) {
            if (i + 2 >= bytes.length) throw 'UTF-8 decode: incomplete 4-byte sequence';
            c = (c & 7) << 18 | (bytes[i] & 63) << 12 | (bytes[++i] & 63) << 6 | bytes[++i] & 63;
          } else throw 'UTF-8 decode: unknown multibyte start 0x' + c.toString(16) + ' at index ' + (i - 1);
          ++i;
        }
        if (c <= 0xffff) s += String.fromCharCode(c);else if (c <= 0x10ffff) {
          c -= 0x10000;
          s += String.fromCharCode(c >> 10 | 0xd800);
          s += String.fromCharCode(c & 0x3FF | 0xdc00);
        } else throw 'UTF-8 decode: code point 0x' + c.toString(16) + ' exceeds UTF-16 reach';
      }
      return s;
    }
    function EncodeUTF8(s) {
      let i = 0;
      const bytes = new Uint8Array(s.length * 4);
      for (let ci = 0; ci != s.length; ci++) {
        let c = s.charCodeAt(ci);
        if (c < 128) {
          bytes[i++] = c;
          continue;
        }
        if (c < 2048) {
          bytes[i++] = c >> 6 | 192;
        } else {
          if (c > 0xd7ff && c < 0xdc00) {
            if (++ci == s.length) throw 'UTF-8 encode: incomplete surrogate pair';
            const c2 = s.charCodeAt(ci);
            if (c2 < 0xdc00 || c2 > 0xdfff) throw 'UTF-8 encode: second char code 0x' + c2.toString(16) + ' at index ' + ci + ' in surrogate pair out of range';
            c = 0x10000 + ((c & 0x03ff) << 10) + (c2 & 0x03ff);
            bytes[i++] = c >> 18 | 240;
            bytes[i++] = c >> 12 & 63 | 128;
          } else {
            bytes[i++] = c >> 12 | 224;
          }
          bytes[i++] = c >> 6 & 63 | 128;
        }
        bytes[i++] = c & 63 | 128;
      }
      return bytes.subarray(0, i);
    }

    /**
     * @public
     */
    class NetworkConnection extends NetworkConnectionBase {
      /** @internal */
      _ws;
      /** @internal */
      _connectTimeout;
      constructor(optsOrUriOrPort, optsOrHostname, opts) {
        super(optsOrUriOrPort, optsOrHostname, opts);
        if (this._port === 0) this._port = 8989;
        if (this._uri === '') this._uri = 'ws://' + this._hostname + ':' + this._port + '/phidgets';
        this._protocol = "www";
      }
      /**
       * Connects to the server. Once the initial connection has succeeded,
       * it will be maintained until close is called.
       *
       * It retryOnFail is true, the initial connect will retry on failure until a connection is established,
       * and connect() will not resolve until the connection is established.
       * Thisis allows connect to be called before the network server is running.
       *
       * If retryOnFail is false (the default), connect() will throw an exception
       * if the connection can not be established.
       *
       * @param retryOnFail - Keep trying to connect if the initial attempt fails. Defaults to false.
       */
      connect(retryOnFail = false) {
        return new Promise((resolve, reject) => {
          this._opened = true;
          if (this.connected === true) {
            resolve();
            return;
          }
          if (retryOnFail) {
            this._resolveConnect = resolve;
            this._maintainConnection();
            return;
          }
          if (this._ws) {
            try {
              this._ws.close();
            } catch {}
            delete this._ws;
          }
          let hasCompleted = false;
          try {
            this._ws = new WebSocket(this._uri);
            this._ws.binaryType = 'arraybuffer';
            this._ws.onopen = () => {
              this._handshake().then(() => {
                if (this._resolveConnect) {
                  this._resolveConnect();
                  delete this._resolveConnect;
                }
                if (this._connectTimeout !== undefined) {
                  clearTimeout(this._connectTimeout);
                  delete this._connectTimeout;
                }
                hasCompleted = true;
                resolve();
              }).catch(err => {
                if (this._connectTimeout !== undefined) {
                  clearTimeout(this._connectTimeout);
                  delete this._connectTimeout;
                }
                if (!hasCompleted) {
                  hasCompleted = true;
                  reject(err);
                }
              });
            };
            this._ws.onclose = () => {
              this._doclose();
              if (!hasCompleted) {
                hasCompleted = true;
                reject(new PhidgetError(exports.ErrorCode.CONNECTION_RESET, "Socket closed"));
              }
            };
            this._ws.onmessage = event => {
              try {
                const array = new Uint8Array(event.data);
                const req = new Request(array);
                let msg;
                if (req.len > 0) {
                  const tmp1 = new Uint8Array(event.data, req.hdrlen, req.len);
                  msg = DecodeUTF8(tmp1);
                }
                this._onmessage(msg, req);
              } catch (e) {
                const msg = "Error handling data from server - resetting connection";
                const perr = new PhidgetError(exports.ErrorCode.UNEXPECTED, msg, e);
                this._doclose();
                if (hasCompleted) {
                  if (this.onError) {
                    try {
                      this.onError(perr.errorCode, perr.message);
                    } catch (err) {
                      logEventException(err);
                    }
                    loginfo(perr.message);
                  } else {
                    logerr(msg, e);
                  }
                } else {
                  hasCompleted = true;
                  reject(perr);
                }
              }
            };
            this._ws.onerror = () => {
              const msg = "websocket error - check that server is available";
              this._doclose();
              if (!hasCompleted) {
                hasCompleted = true;
                reject(new PhidgetError(exports.ErrorCode.CONNECTION_REFUSED, msg));
                return;
              }
              if (this.onError) {
                try {
                  this.onError(exports.ErrorCode.CONNECTION_REFUSED, msg);
                } catch (err) {
                  logEventException(err);
                }
                loginfo(msg);
              } else {
                logerr(msg);
              }
            };
            this._connectTimeout = setTimeout(() => {
              delete this._connectTimeout;
              this._doclose();
              if (!hasCompleted) {
                hasCompleted = true;
                reject(new PhidgetError(exports.ErrorCode.TIMEOUT, "Connection Timed Out"));
              }
            }, this._timeout);
          } catch (err) {
            if (this._connectTimeout !== undefined) {
              clearTimeout(this._connectTimeout);
              delete this._connectTimeout;
            }
            if (!hasCompleted) {
              hasCompleted = true;
              reject(new PhidgetError(exports.ErrorCode.UNEXPECTED, 'Error in connect', err));
            }
          }
        });
      }
      /** @internal */
      _closesocket() {
        if (this.connected === true) {
          if (this.onDisconnect) {
            try {
              this.onDisconnect();
            } catch (err) {
              logEventException(err);
            }
          }
        }
        this.connected = false;
        if (this._connectTimeout !== undefined) {
          clearTimeout(this._connectTimeout);
          delete this._connectTimeout;
        }
        if (this._ws != undefined) {
          try {
            this._ws.onopen = null;
            this._ws.onclose = null;
            this._ws.onmessage = null;
            this._ws.onerror = null;
            this._ws.close();
          } catch {}
          delete this._ws;
        }
        this._generation++;
      }
      /** @internal */
      _send(req, data) {
        try {
          if (!this._ws || this._ws.readyState != WebSocket.OPEN) throw new PhidgetError(exports.ErrorCode.UNEXPECTED, 'invalid websocket state');
          if (data.length > 0) {
            const dataArr = EncodeUTF8(data);
            req.len = dataArr.length;
            this._ws.send(req.buffer);
            this._ws.send(dataArr);
          } else {
            this._ws.send(req.buffer);
          }
        } catch (e) {
          let msg;
          if (typeof e === 'string') msg = e;else if (e instanceof Error) msg = e.message;else msg = 'Error in connect';
          throw new PhidgetError(exports.ErrorCode.UNEXPECTED, msg);
        }
      }
      /** @internal */
      _hash(challenge) {
        const digest = sha256hash(challenge);
        let bin = '';
        for (let i = 0; i < digest.length; i += 2) {
          const b = parseInt(digest.substring(i, i + 2), 16);
          bin += String.fromCharCode(b);
        }
        return btoa(bin);
      }
      /** @internal */
      _createSalt(len) {
        const buf = new Uint8Array(len);
        crypto.getRandomValues(buf);
        return btoa(String.fromCharCode(...buf)).substring(len);
      }
    }

    /**
     * The Accelerometer class is used to gather acceleration data from Phidget accelerometer boards. Phidget accelerometers usually have multiple sensors, each oriented in a different axis, so multiple dimensions of acceleration can be recorded.
     *
     * If the Phidget you're using also has a gyroscope and a magnetometer, you may want to use the Spatial class in order to get all of the data at the same time, in a single event.
     * @public
     */
    class AccelerometerBase extends PhidgetChannel {
      /** @internal */
      data;
      onAccelerationChange = null;
      /** @internal */
      _gotAccelerationChangeErrorEvent;
      constructor(ch) {
        super(ch);
        this._class = exports.ChannelClass.ACCELEROMETER;
        this.name = "Accelerometer";
        this.data = this._initData();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 46:
            this.data.accelerationChangeTrigger = bp.entries[0].v;
            this._FIREPropertyChange('AccelerationChangeTrigger', bp);
            break;
          case 54:
            if (bp.entryCount > 1) this.data.dataInterval = bp.entries[1].v;else this.data.dataInterval = bp.entries[0].v;
            this._FIREPropertyChange('DataInterval', bp);
            this._FIREPropertyChange('DataRate', bp);
            break;
          case 170:
            this.data.heatingEnabled = bp.entries[0].v;
            this._FIREPropertyChange('HeatingEnabled', bp);
            break;
          case 145:
            this.data.precision = bp.entries[0].v;
            this._FIREPropertyChange('Precision', bp);
            break;
          case 1:
            {
              this.data.acceleration = bp.entries[0].v;
              this.data.timestamp = bp.entries[1].v;
              if (this._isAttachedDone && this.onAccelerationChange) {
                try {
                  this.onAccelerationChange(this.data.acceleration, this.data.timestamp);
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          default:
            throw new PhidgetError(exports.ErrorCode.INVALID_PACKET, "Unsupported bridge packet: 0x" + bp.vpkt.toString(16));
        }
      }
      /** @internal */
      _initData() {
        return {
          dataInterval: 1e+300,
          timestamp: 1e+300,
          maxDataInterval: 4294967295,
          minDataRate: 1e+300,
          maxDataRate: 1e+300,
          maxAcceleration: [1e+300, 1e+300, 1e+300],
          maxAccelerationChangeTrigger: 1e+300,
          minDataInterval: 4294967295,
          minAcceleration: [1e+300, 1e+300, 1e+300],
          minAccelerationChangeTrigger: 1e+300,
          acceleration: [1e+300, 1e+300, 1e+300],
          accelerationChangeTrigger: 1e+300,
          axisCount: 2147483647,
          precision: 2147483647,
          heatingEnabled: 2
        };
      }
      /** @internal */
      _initAfterOpen() {}
      /** @internal */
      async _setDefaults() {}
      /** @internal */
      _hasInitialState() {
        return true;
      }
      /** @internal */
      _fireInitialEvents() {}
      /**
       * The most recent acceleration value that the channel has reported.
       *
       * *   This value will always be between `minAcceleration` and `maxAcceleration`.
       * @throws `PhidgetError`
       */
      get acceleration() {
        return this.getAcceleration();
      }
      /**
       * The minimum value the `AccelerationChange` event will report.
       * @throws `PhidgetError`
       */
      get minAcceleration() {
        return this.getMinAcceleration();
      }
      /**
       * The maximum value the `AccelerationChange` event will report.
       * @throws `PhidgetError`
       */
      get maxAcceleration() {
        return this.getMaxAcceleration();
      }
      /**
       * The channel will not issue a `AccelerationChange` event until the acceleration value has changed by the amount specified by the `accelerationChangeTrigger`.
       *
       * *   Setting the `accelerationChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @throws `PhidgetError`
       */
      get accelerationChangeTrigger() {
        return this.getAccelerationChangeTrigger();
      }
      /**
       * The minimum value that `accelerationChangeTrigger` can be set to.
       * @throws `PhidgetError`
       */
      get minAccelerationChangeTrigger() {
        return this.getMinAccelerationChangeTrigger();
      }
      /**
       * The maximum value that `accelerationChangeTrigger` can be set to.
       * @throws `PhidgetError`
       */
      get maxAccelerationChangeTrigger() {
        return this.getMaxAccelerationChangeTrigger();
      }
      /**
       * The number of axes the channel can measure acceleration on.
       *
       * *   See your device's User Guide for more information about the number of axes and their orientation.
       * @throws `PhidgetError`
       */
      get axisCount() {
        return this.getAxisCount();
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `AccelerationChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between `AccelerationChange` events can also be affected by the `accelerationChangeTrigger`.
       * @throws `PhidgetError`
       */
      get dataInterval() {
        return this.getDataInterval();
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get minDataInterval() {
        return this.getMinDataInterval();
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataInterval() {
        return this.getMaxDataInterval();
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       */
      get dataRate() {
        return this.getDataRate();
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get minDataRate() {
        return this.getMinDataRate();
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataRate() {
        return this.getMaxDataRate();
      }
      /**
       * Set to TRUE to enable the temperature stabilization feature of this device. This enables onboard heating elements to bring the board up to a known temperature to minimize ambient temerature effects on the sensor's reading. You can leave this setting FALSE to conserve power consumption.
       *
       * If you enable heating, it is strongly recommended to keep the board in its enclosure to keep it insulated from moving air.
       *
       * This property is shared by any and all spatial-related objects on this device (Accelerometer, Gyroscope, Magnetometer, Spatial)
       * @throws `PhidgetError`
       */
      get heatingEnabled() {
        return this.getHeatingEnabled();
      }
      /**
       * Selects between high/low precision sensing chips.
       * @throws `PhidgetError`
       * @internal
       */
      get precision() {
        return this.getPrecision();
      }
      /**
       * The most recent timestamp value that the channel has reported. This is an extremely accurate time measurement streamed from the device.
       *
       * *   If your application requires a time measurement, you should use this value over a local software timestamp.
       * @throws `PhidgetError`
       */
      get timestamp() {
        return this.getTimestamp();
      }
      /**
       * The most recent acceleration value that the channel has reported.
       *
       * *   This value will always be between `minAcceleration` and `maxAcceleration`.
       * @returns The acceleration values
       * @throws `PhidgetError`
       */
      getAcceleration() {
        var _context;
        this._assertOpen();
        if (_includesInstanceProperty(_context = this.data.acceleration).call(_context, 1e+300)) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.acceleration;
      }
      /**
       * The minimum value the `AccelerationChange` event will report.
       * @returns The minimum acceleration value
       * @throws `PhidgetError`
       */
      getMinAcceleration() {
        var _context2;
        this._assertOpen();
        if (_includesInstanceProperty(_context2 = this.data.minAcceleration).call(_context2, 1e+300)) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minAcceleration;
      }
      /**
       * The maximum value the `AccelerationChange` event will report.
       * @returns The maximum acceleration values
       * @throws `PhidgetError`
       */
      getMaxAcceleration() {
        var _context3;
        this._assertOpen();
        if (_includesInstanceProperty(_context3 = this.data.maxAcceleration).call(_context3, 1e+300)) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxAcceleration;
      }
      /**
       * The channel will not issue a `AccelerationChange` event until the acceleration value has changed by the amount specified by the `accelerationChangeTrigger`.
       *
       * *   Setting the `accelerationChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getAccelerationChangeTrigger() {
        this._assertOpen();
        if (this.data.accelerationChangeTrigger === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.accelerationChangeTrigger;
      }
      /**
       * The channel will not issue a `AccelerationChange` event until the acceleration value has changed by the amount specified by the `accelerationChangeTrigger`.
       *
       * *   Setting the `accelerationChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @throws `PhidgetError`
       * @param accelerationChangeTrigger - The change trigger value
       */
      async setAccelerationChangeTrigger(accelerationChangeTrigger) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: accelerationChangeTrigger
        });
        await bp.send(this._ch, 46);
      }
      /**
       * The minimum value that `accelerationChangeTrigger` can be set to.
       * @returns The minimum change trigger value
       * @throws `PhidgetError`
       */
      getMinAccelerationChangeTrigger() {
        this._assertOpen();
        if (this.data.minAccelerationChangeTrigger === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minAccelerationChangeTrigger;
      }
      /**
       * The maximum value that `accelerationChangeTrigger` can be set to.
       * @returns The maximum change trigger value
       * @throws `PhidgetError`
       */
      getMaxAccelerationChangeTrigger() {
        this._assertOpen();
        if (this.data.maxAccelerationChangeTrigger === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxAccelerationChangeTrigger;
      }
      /**
       * The number of axes the channel can measure acceleration on.
       *
       * *   See your device's User Guide for more information about the number of axes and their orientation.
       * @returns The number of axes
       * @throws `PhidgetError`
       */
      getAxisCount() {
        this._assertOpen();
        if (this.data.axisCount === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.axisCount;
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `AccelerationChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between `AccelerationChange` events can also be affected by the `accelerationChangeTrigger`.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getDataInterval() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.dataInterval;
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `AccelerationChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between `AccelerationChange` events can also be affected by the `accelerationChangeTrigger`.
       * @throws `PhidgetError`
       * @param dataInterval - The data interval value
       */
      async setDataInterval(dataInterval) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: dataInterval
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @returns The minimum data interval value
       * @throws `PhidgetError`
       */
      getMinDataInterval() {
        this._assertOpen();
        if (this.data.minDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataInterval;
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMaxDataInterval() {
        this._assertOpen();
        if (this.data.maxDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @returns The data rate for the channel
       * @throws `PhidgetError`
       */
      getDataRate() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return 1000.0 / this.data.dataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       * @param dataRate - The data rate for the channel
       */
      async setDataRate(dataRate) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: Math.round(1000.0 / dataRate)
        });
        bp.set({
          name: "1",
          type: "g",
          value: 1000.0 / dataRate
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMinDataRate() {
        this._assertOpen();
        if (this.data.minDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataRate;
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMaxDataRate() {
        this._assertOpen();
        if (this.data.maxDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataRate;
      }
      /**
       * Set to TRUE to enable the temperature stabilization feature of this device. This enables onboard heating elements to bring the board up to a known temperature to minimize ambient temerature effects on the sensor's reading. You can leave this setting FALSE to conserve power consumption.
       *
       * If you enable heating, it is strongly recommended to keep the board in its enclosure to keep it insulated from moving air.
       *
       * This property is shared by any and all spatial-related objects on this device (Accelerometer, Gyroscope, Magnetometer, Spatial)
       * @returns Whether self-heating temperature stabilization is enabled
       * @throws `PhidgetError`
       */
      getHeatingEnabled() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 352:
          case 357:
          case 362:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.heatingEnabled === 2) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return !!this.data.heatingEnabled;
      }
      /**
       * Set to TRUE to enable the temperature stabilization feature of this device. This enables onboard heating elements to bring the board up to a known temperature to minimize ambient temerature effects on the sensor's reading. You can leave this setting FALSE to conserve power consumption.
       *
       * If you enable heating, it is strongly recommended to keep the board in its enclosure to keep it insulated from moving air.
       *
       * This property is shared by any and all spatial-related objects on this device (Accelerometer, Gyroscope, Magnetometer, Spatial)
       * @throws `PhidgetError`
       * @param heatingEnabled - Whether self-heating temperature stabilization is enabled
       */
      async setHeatingEnabled(heatingEnabled) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: heatingEnabled ? 1 : 0
        });
        await bp.send(this._ch, 170);
      }
      /**
       * Selects between high/low precision sensing chips.
       * @returns The sensor precision value
       * @throws `PhidgetError`
       * @internal
       */
      getPrecision() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 10:
          case 124:
          case 142:
          case 478:
          case 157:
          case 367:
          case 350:
          case 351:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.precision === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.precision;
      }
      /**
       * Selects between high/low precision sensing chips.
       * @throws `PhidgetError`
       * @param precision - The sensor precision value
       * @internal
       */
      async setPrecision(precision) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: precision
        });
        await bp.send(this._ch, 145);
      }
      /**
       * The most recent timestamp value that the channel has reported. This is an extremely accurate time measurement streamed from the device.
       *
       * *   If your application requires a time measurement, you should use this value over a local software timestamp.
       * @returns The timestamp value
       * @throws `PhidgetError`
       */
      getTimestamp() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 367:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.timestamp === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.timestamp;
      }
    }

    /** @public */
    class Accelerometer extends AccelerometerBase {
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 10:
            if (bp.entryCount > 1) this.data.dataInterval = bp.getNumber(1);else this.data.dataInterval = bp.getNumber(0);
            this._FIREPropertyChange('DataInterval');
            this._FIREPropertyChange('DataRate');
            break;
          case 179:
            this.data.heatingEnabled = bp.entries[0].v;
            this._FIREPropertyChange('HeatingEnabled', bp);
            break;
          default:
            super._bridgeInput(bp);
            break;
        }
      }
      /** @internal */
      _errorHandler(code) {
        switch (code) {
          case exports.ErrorEventCode.SATURATION:
            this.data.acceleration = [1e+300, 1e+300, 1e+300];
            this.data.timestamp = 1e+300;
            this._gotAccelerationChangeErrorEvent = true;
            break;
        }
      }
    }

    /**
     * The BLDC Motor class controls the power applied to attached brushless DC motors to affect its speed and direction. It can also contain various other control and monitoring functions that aid in the control of brushless DC motors.
     * @public
     */
    class BLDCMotorBase extends PhidgetChannel {
      /** @internal */
      data;
      onBrakingStrengthChange = null;
      /** @internal */
      _gotBrakingStrengthChangeErrorEvent;
      onPositionChange = null;
      /** @internal */
      _gotPositionChangeErrorEvent;
      onVelocityUpdate = null;
      /** @internal */
      _gotVelocityUpdateErrorEvent;
      constructor(ch) {
        super(ch);
        this._class = exports.ChannelClass.BLDC_MOTOR;
        this.name = "BLDCMotor";
        this.data = this._initData();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 40:
            this.data.acceleration = bp.entries[0].v;
            this._FIREPropertyChange('Acceleration', bp);
            break;
          case 51:
            this.data.currentLimit = bp.entries[0].v;
            this._FIREPropertyChange('CurrentLimit', bp);
            break;
          case 54:
            if (bp.entryCount > 1) this.data.dataInterval = bp.entries[1].v;else this.data.dataInterval = bp.entries[0].v;
            this._FIREPropertyChange('DataInterval', bp);
            this._FIREPropertyChange('DataRate', bp);
            break;
          case 186:
            this.data.driveMode = bp.entries[0].v;
            this._FIREPropertyChange('DriveMode', bp);
            break;
          case 146:
            break;
          case 193:
            this.data.failsafeBrakingEnabled = bp.entries[0].v;
            this._FIREPropertyChange('FailsafeBrakingEnabled', bp);
            break;
          case 192:
            this.data.failsafeCurrentLimit = bp.entries[0].v;
            this._FIREPropertyChange('FailsafeCurrentLimit', bp);
            break;
          case 184:
            this.data.inductance = bp.entries[0].v;
            this._FIREPropertyChange('Inductance', bp);
            break;
          case 147:
            break;
          case 141:
            this.data.stallVelocity = bp.entries[0].v;
            this._FIREPropertyChange('StallVelocity', bp);
            break;
          case 194:
            this.data.surgeCurrentLimit = bp.entries[0].v;
            this._FIREPropertyChange('SurgeCurrentLimit', bp);
            break;
          case 44:
            this.data.targetBrakingStrength = bp.entries[0].v;
            this._FIREPropertyChange('TargetBrakingStrength', bp);
            break;
          case 55:
            this.data.targetVelocity = bp.entries[0].v;
            this._FIREPropertyChange('TargetVelocity', bp);
            break;
          case 121:
            {
              this.data.brakingStrength = bp.entries[0].v;
              if (this._isAttachedDone && this.onBrakingStrengthChange) {
                try {
                  this.onBrakingStrengthChange(this.data.brakingStrength);
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          case 16:
            {
              this.data.velocity = bp.entries[0].v;
              if (this._isAttachedDone && this.onVelocityUpdate) {
                try {
                  this.onVelocityUpdate(this.data.velocity);
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          default:
            throw new PhidgetError(exports.ErrorCode.INVALID_PACKET, "Unsupported bridge packet: 0x" + bp.vpkt.toString(16));
        }
      }
      /** @internal */
      _initData() {
        return {
          positionOffset: 0,
          dataInterval: 1e+300,
          minDataInterval: 4294967295,
          maxDataInterval: 4294967295,
          minDataRate: 1e+300,
          maxDataRate: 1e+300,
          currentLimit: 1e+300,
          maxCurrentLimit: 1e+300,
          minCurrentLimit: 1e+300,
          surgeCurrentLimit: 1e+300,
          maxSurgeCurrentLimit: 1e+300,
          minSurgeCurrentLimit: 1e+300,
          activeCurrentLimit: 1e+300,
          acceleration: 1e+300,
          targetBrakingStrength: 1e+300,
          maxAcceleration: 1e+300,
          maxBrakingStrength: 1e+300,
          maxVelocity: 1e+300,
          maxPosition: 9223372036854776000,
          minVelocity: 1e+300,
          minAcceleration: 1e+300,
          minBrakingStrength: 1e+300,
          minPosition: 9223372036854776000,
          position: 9223372036854776000,
          rescaleFactor: 1e+300,
          targetVelocity: 1e+300,
          velocity: 1e+300,
          brakingStrength: 1e+300,
          stallVelocity: 1e+300,
          minStallVelocity: 1e+300,
          maxStallVelocity: 1e+300,
          maxFailsafeTime: 4294967295,
          minFailsafeTime: 4294967295,
          inductance: 1e+300,
          maxInductance: 1e+300,
          minInductance: 1e+300,
          driveMode: 2147483647,
          failsafeCurrentLimit: 1e+300,
          failsafeBrakingEnabled: 2
        };
      }
      /** @internal */
      _initAfterOpen() {}
      /** @internal */
      async _setDefaults() {}
      /** @internal */
      _hasInitialState() {
        return true;
      }
      /** @internal */
      _fireInitialEvents() {}
      /**
       * The rate at which the controller can change the motor's `velocity`.
       *
       *
       * For more information about `acceleration`, visit our [BLDCMotor API Guide](https://www.phidgets.com/docs/BLDCMotor_API_Guide#Acceleration)
       * @throws `PhidgetError`
       */
      get acceleration() {
        return this.getAcceleration();
      }
      /**
       * The minimum value that `acceleration` can be set to.
       * @throws `PhidgetError`
       */
      get minAcceleration() {
        return this.getMinAcceleration();
      }
      /**
       * The maximum value that `acceleration` can be set to.
       * @throws `PhidgetError`
       */
      get maxAcceleration() {
        return this.getMaxAcceleration();
      }
      /**
       * The current limit that the controller is actively following. The `surgeCurrentLimit`, `currentLimit`, and temperature will impact this value.
       *
       *
       * For more information about `activeCurrentLimit`, visit our [BLDCMotor API Guide](https://www.phidgets.com/docs/BLDCMotor_API_Guide#Active_Current_Limit)
       * @throws `PhidgetError`
       */
      get activeCurrentLimit() {
        return this.getActiveCurrentLimit();
      }
      /**
       * This setting allows you to choose whether the motor will resist being turned when it is not being driven forward or reverse (`velocity` = 0).
       *
       * *   Setting `brakingEnabled` to FALSE corresponds to free-wheeling. This means:
       *     *   The motor will continue to rotate after the controller is no longer driving the motor (`velocity` = 0), due to its momentum.
       *     *   The motor shaft will provide little resistance to being turned when it is stopped.
       * *   Setting `brakingEnabled` to TRUE will engage electrical braking of the DC motor. This means:
       *     *   The motor will stop more quickly if it is in motion when braking is requested.
       *     *   The motor shaft will resist rotation by outside forces.
       * *   Braking will be added gradually, according to the `acceleration` setting, once the motor controller's `velocity` reaches 0.0
       * *   Braking will be immediately stopped when a new (non-zero) `targetVelocity` is set, and the motor will accelerate to the requested velocity.
       * *   Braking mode is enabled by setting the `velocity` to 0.0
       * @throws `PhidgetError`
       */
      get brakingEnabled() {
        return this.getBrakingEnabled();
      }
      /**
       * The most recent braking strength value that the controller has reported.
       * @throws `PhidgetError`
       */
      get brakingStrength() {
        return this.getBrakingStrength();
      }
      /**
       * The minimum value that `brakingStrength` can be set to.
       * @throws `PhidgetError`
       */
      get minBrakingStrength() {
        return this.getMinBrakingStrength();
      }
      /**
       * The maximum value that `brakingStrength` can be set to.
       * @throws `PhidgetError`
       */
      get maxBrakingStrength() {
        return this.getMaxBrakingStrength();
      }
      /**
       * The controller will limit the current through the motor to the `currentLimit` value.
       *
       *
       * For more information about `currentLimit`, visit our [BLDCMotor API Guide](https://www.phidgets.com/docs/BLDCMotor_API_Guide#Current_Limit)
       * @throws `PhidgetError`
       */
      get currentLimit() {
        return this.getCurrentLimit();
      }
      /**
       * The minimum value that `currentLimit` can be set to.
       * @throws `PhidgetError`
       */
      get minCurrentLimit() {
        return this.getMinCurrentLimit();
      }
      /**
       * The maximum value that `currentLimit` can be set to.
       * @throws `PhidgetError`
       */
      get maxCurrentLimit() {
        return this.getMaxCurrentLimit();
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `VelocityUpdate` / `PositionChange` / `BrakingStrengthChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * @throws `PhidgetError`
       */
      get dataInterval() {
        return this.getDataInterval();
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get minDataInterval() {
        return this.getMinDataInterval();
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataInterval() {
        return this.getMaxDataInterval();
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       */
      get dataRate() {
        return this.getDataRate();
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get minDataRate() {
        return this.getMinDataRate();
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataRate() {
        return this.getMaxDataRate();
      }
      /**
       * This setting impacts how your motor decelerates and the amount of current that is available to your motor at any given moment.
       *
       *
       * For more information about `driveMode`, visit our [BLDCMotor API Guide](https://www.phidgets.com/docs/BLDCMotor_API_Guide#Drive_Mode)
       * @throws `PhidgetError`
       */
      get driveMode() {
        return this.getDriveMode();
      }
      /**
       * This setting allows you to choose whether motor will forcibly stop once it enters a **FAILSAFE** state.
       *
       * *   A setting of FALSE will simply stop applying power to the motor, allowing it to spin down naturally.
       * *   A setting of TRUE will apply braking up to the `failsafeCurrentLimit`, actively stopping the motor
       *
       *
       * For more information about `failsafeBrakingEnabled`, visit our [BLDCMotor API Guide](https://www.phidgets.com/docs/BLDCMotor_API_Guide#Failsafe_Braking_Enabled)
       * @throws `PhidgetError`
       */
      get failsafeBrakingEnabled() {
        return this.getFailsafeBrakingEnabled();
      }
      /**
       * When the controller enters a **FAILSAFE** state, the controller will limit the current through the motor to the `failsafeCurrentLimit` value.
       *
       *
       * For more information about `failsafeCurrentLimit`, visit our [BLDCMotor API Guide](https://www.phidgets.com/docs/BLDCMotor_API_Guide#Failsafe_Current_Limit)
       * @throws `PhidgetError`
       */
      get failsafeCurrentLimit() {
        return this.getFailsafeCurrentLimit();
      }
      /**
       * The minimum value that `failsafeTime` can be set to when calling `enableFailsafe()`.
       * @throws `PhidgetError`
       */
      get minFailsafeTime() {
        return this.getMinFailsafeTime();
      }
      /**
       * The maximum value that `failsafeTime` can be set to when calling `enableFailsafe()`.
       * @throws `PhidgetError`
       */
      get maxFailsafeTime() {
        return this.getMaxFailsafeTime();
      }
      /**
       * The controller will attempt to measure the inductance of your motor when opened. This value is used to improve control of the motor.
       *
       * *   Set this value during the `Phidget.Attach` event to skip motor characterization (including the audible beeps). You can use a previously saved `inductance` value, or information from your motor's datasheet.
       *
       *
       * For more information about `inductance`, visit our [BLDCMotor API Guide](https://www.phidgets.com/docs/BLDCMotor_API_Guide#Motor_Inductance)
       * @throws `PhidgetError`
       */
      get inductance() {
        return this.getInductance();
      }
      /**
       * The minimum value that `inductance` can be set to. See `inductance` for details.
       * @throws `PhidgetError`
       */
      get minInductance() {
        return this.getMinInductance();
      }
      /**
       * The maximum value that `inductance` can be set to. See `inductance` for details.
       * @throws `PhidgetError`
       */
      get maxInductance() {
        return this.getMaxInductance();
      }
      /**
       * The most recent position value that the controller has reported.
       *
       * *   Position values are calculated using Hall Effect sensors mounted on the motor, therefore, the resolution of position depends on the motor you are using.
       * *   Units for `position` can be set by the user through the `rescaleFactor`. The `rescaleFactor` allows you to use more intuitive units such as rotations, or degrees. For more information on how to apply the `rescaleFactor` to your application, see your controller's User Guide.
       *
       *
       * For more information about `position`, visit our [BLDCMotor API Guide](https://www.phidgets.com/docs/BLDCMotor_API_Guide#Position)
       * @throws `PhidgetError`
       */
      get position() {
        return this.getPosition();
      }
      /**
       * The lower bound of `position`.
       * @throws `PhidgetError`
       */
      get minPosition() {
        return this.getMinPosition();
      }
      /**
       * The upper bound of `position`.
       * @throws `PhidgetError`
       */
      get maxPosition() {
        return this.getMaxPosition();
      }
      /**
       * Change the units of your parameters so that your application is more intuitive.
       *
       *
       * For more information about `rescaleFactor`, visit our [BLDCMotor API Guide](https://www.phidgets.com/docs/BLDCMotor_API_Guide#Rescale_Factor)
       * @throws `PhidgetError`
       */
      get rescaleFactor() {
        return this.getRescaleFactor();
      }
      set rescaleFactor(rescaleFactor) {
        this.setRescaleFactor(rescaleFactor);
      }
      /**
       * Before reading this description, it is important to note the difference between the units of `stallVelocity` and `velocity`.
       *
       * *   `velocity` is a number between -1 and 1 with units of 'duty cycle'. It simply represents the average voltage across the motor.
       * *   `stallVelocity` represents a real velocity (e.g. m/s, RPM, etc.) and the units are determined by the `rescaleFactor`. With a `rescaleFactor` of 1, the default units would be in commutations per second.
       *
       * If the load on your motor is large, your motor may begin rotating more slowly, or even fully stall. Depending on the voltage across your motor, this may result in a large amount of current through both the controller and the motor. In order to prevent damage in these situations, you can use the `stallVelocity` property.
       *
       * The `stallVelocity` should be set to the lowest velocity you would expect from your motor. The controller will then monitor the motor's velocity, as well as the `velocity`, and prevent a 'dangerous stall' from occuring. If the controller detects a dangerous stall, it will immediately reduce the `velocity` (i.e. average voltage) to 0 and an error will be reported to your program.
       *
       * *   A 'dangerous stall' will occur faster when the `velocity` is higher (i.e. when the average voltage across the motor is higher)
       * *   A 'dangerous stall' will occur faster as (`stallVelocity` - motor velocity) becomes larger .
       *
       * Setting `stallVelocity` to 0 will turn off stall protection functionality.
       * @throws `PhidgetError`
       */
      get stallVelocity() {
        return this.getStallVelocity();
      }
      /**
       * The lower bound of `stallVelocity`.
       * @throws `PhidgetError`
       */
      get minStallVelocity() {
        return this.getMinStallVelocity();
      }
      /**
       * The upper bound of `stallVelocity`.
       * @throws `PhidgetError`
       */
      get maxStallVelocity() {
        return this.getMaxStallVelocity();
      }
      /**
       * The `surgeCurrentLimit` allows for increased performance from your motor. The controller will limit the current through your motor to the `surgeCurrentLimit` briefly, then scale current down to the `currentLimit`.
       *
       * *   View `activeCurrentLimit` for information about what current limit the controller is actively following.
       *
       *
       * For more information about `surgeCurrentLimit`, visit our [BLDCMotor API Guide](https://www.phidgets.com/docs/BLDCMotor_API_Guide#Surge_Current_Limit)
       * @throws `PhidgetError`
       */
      get surgeCurrentLimit() {
        return this.getSurgeCurrentLimit();
      }
      /**
       * The minimum value that `surgeCurrentLimit` can be set to.
       * @throws `PhidgetError`
       */
      get minSurgeCurrentLimit() {
        return this.getMinSurgeCurrentLimit();
      }
      /**
       * The maximum value that `surgeCurrentLimit` can be set to.
       * @throws `PhidgetError`
       */
      get maxSurgeCurrentLimit() {
        return this.getMaxSurgeCurrentLimit();
      }
      /**
       * When a motor is not being actively driven forward or reverse, you can choose if the motor will be allowed to freely turn, or will resist being turned.
       *
       * *   A low `targetBrakingStrength` value corresponds to free wheeling, this will have the following effects:
       *     *   The motor will continue to rotate after the controller is no longer driving the motor (i.e. `velocity` is 0), due to inertia.
       *     *   The motor shaft will provide little resistance to being turned when it is stopped.
       * *   A higher `targetBrakingStrength` value will resist being turned, this will have the following effects:
       *     *   The motor will more stop more quickly if it is in motion and braking has been requested. It will fight against the rotation of the shaft.
       * *   Braking mode is enabled by setting the `velocity` to `minVelocity`
       * @throws `PhidgetError`
       */
      get targetBrakingStrength() {
        return this.getTargetBrakingStrength();
      }
      /**
       * The average voltage across the motor is based on the `targetVelocity` value.
       *
       * *   At a constant load, increasing the target velocity will increase the speed of the motor.
       * *   `targetVelocity` is bounded by -`maxVelocity` and +`maxVelocity`, where a sign change (±) is indicative of a direction change.
       * *   Setting `targetVelocity` to `minVelocity` will stop the motor. See `brakingEnabled` for more information on stopping the motor.
       *
       *
       * For more information about `targetVelocity`, visit our [BLDCMotor API Guide](https://www.phidgets.com/docs/BLDCMotor_API_Guide#Target_Velocity)
       * @throws `PhidgetError`
       */
      get targetVelocity() {
        return this.getTargetVelocity();
      }
      /**
       * The most recent `velocity` value that the controller has reported.
       *
       *
       * For more information about `velocity`, visit our [BLDCMotor API Guide](https://www.phidgets.com/docs/BLDCMotor_API_Guide#Velocity)
       * @throws `PhidgetError`
       */
      get velocity() {
        return this.getVelocity();
      }
      /**
       * The minimum value that `targetVelocity` can be set to.
       *
       * *   Set the `targetVelocity` to `minVelocity` to stop the motor. See `brakingEnabled` for more information on stopping the motor.
       * *   `targetVelocity` is bounded by -`maxVelocity` and +`maxVelocity`, where a sign change (±) is indicative of a direction change.
       * @throws `PhidgetError`
       */
      get minVelocity() {
        return this.getMinVelocity();
      }
      /**
       * The maximum value that `targetVelocity` can be set to.
       *
       * *   `targetVelocity` is bounded by -`maxVelocity` and +`maxVelocity`, where a sign change (±) is indicative of a direction change.
       * @throws `PhidgetError`
       */
      get maxVelocity() {
        return this.getMaxVelocity();
      }
      /**
       * The rate at which the controller can change the motor's `velocity`.
       *
       *
       * For more information about `acceleration`, visit our [BLDCMotor API Guide](https://www.phidgets.com/docs/BLDCMotor_API_Guide#Acceleration)
       * @returns The acceleration value
       * @throws `PhidgetError`
       */
      getAcceleration() {
        this._assertOpen();
        if (this.data.acceleration === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.acceleration;
      }
      /**
       * The rate at which the controller can change the motor's `velocity`.
       *
       *
       * For more information about `acceleration`, visit our [BLDCMotor API Guide](https://www.phidgets.com/docs/BLDCMotor_API_Guide#Acceleration)
       * @throws `PhidgetError`
       * @param acceleration - The acceleration value
       */
      async setAcceleration(acceleration) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: acceleration
        });
        await bp.send(this._ch, 40);
      }
      /**
       * The minimum value that `acceleration` can be set to.
       * @returns The acceleration value.
       * @throws `PhidgetError`
       */
      getMinAcceleration() {
        this._assertOpen();
        if (this.data.minAcceleration === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minAcceleration;
      }
      /**
       * The maximum value that `acceleration` can be set to.
       * @returns The acceleration value.
       * @throws `PhidgetError`
       */
      getMaxAcceleration() {
        this._assertOpen();
        if (this.data.maxAcceleration === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxAcceleration;
      }
      /**
       * The current limit that the controller is actively following. The `surgeCurrentLimit`, `currentLimit`, and temperature will impact this value.
       *
       *
       * For more information about `activeCurrentLimit`, visit our [BLDCMotor API Guide](https://www.phidgets.com/docs/BLDCMotor_API_Guide#Active_Current_Limit)
       * @returns The active current limit value
       * @throws `PhidgetError`
       */
      getActiveCurrentLimit() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 300:
          case 307:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.activeCurrentLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.activeCurrentLimit;
      }
      /**
       * The most recent braking strength value that the controller has reported.
       * @returns The braking strength value
       * @throws `PhidgetError`
       */
      getBrakingStrength() {
        this._assertOpen();
        if (this.data.brakingStrength === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.brakingStrength;
      }
      /**
       * The minimum value that `brakingStrength` can be set to.
       * @returns The braking value
       * @throws `PhidgetError`
       */
      getMinBrakingStrength() {
        this._assertOpen();
        if (this.data.minBrakingStrength === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minBrakingStrength;
      }
      /**
       * The maximum value that `brakingStrength` can be set to.
       * @returns The braking value
       * @throws `PhidgetError`
       */
      getMaxBrakingStrength() {
        this._assertOpen();
        if (this.data.maxBrakingStrength === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxBrakingStrength;
      }
      /**
       * The controller will limit the current through the motor to the `currentLimit` value.
       *
       *
       * For more information about `currentLimit`, visit our [BLDCMotor API Guide](https://www.phidgets.com/docs/BLDCMotor_API_Guide#Current_Limit)
       * @returns The current value
       * @throws `PhidgetError`
       */
      getCurrentLimit() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 300:
          case 307:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.currentLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.currentLimit;
      }
      /**
       * The controller will limit the current through the motor to the `currentLimit` value.
       *
       *
       * For more information about `currentLimit`, visit our [BLDCMotor API Guide](https://www.phidgets.com/docs/BLDCMotor_API_Guide#Current_Limit)
       * @throws `PhidgetError`
       * @param currentLimit - The current value
       */
      async setCurrentLimit(currentLimit) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: currentLimit
        });
        await bp.send(this._ch, 51);
      }
      /**
       * The minimum value that `currentLimit` can be set to.
       * @returns The current value
       * @throws `PhidgetError`
       */
      getMinCurrentLimit() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 300:
          case 307:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.minCurrentLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minCurrentLimit;
      }
      /**
       * The maximum value that `currentLimit` can be set to.
       * @returns The current value
       * @throws `PhidgetError`
       */
      getMaxCurrentLimit() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 300:
          case 307:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.maxCurrentLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxCurrentLimit;
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `VelocityUpdate` / `PositionChange` / `BrakingStrengthChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getDataInterval() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.dataInterval;
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `VelocityUpdate` / `PositionChange` / `BrakingStrengthChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * @throws `PhidgetError`
       * @param dataInterval - The data interval value
       */
      async setDataInterval(dataInterval) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: dataInterval
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMinDataInterval() {
        this._assertOpen();
        if (this.data.minDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataInterval;
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMaxDataInterval() {
        this._assertOpen();
        if (this.data.maxDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @returns The data rate for the channel
       * @throws `PhidgetError`
       */
      getDataRate() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return 1000.0 / this.data.dataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       * @param dataRate - The data rate for the channel
       */
      async setDataRate(dataRate) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: Math.round(1000.0 / dataRate)
        });
        bp.set({
          name: "1",
          type: "g",
          value: 1000.0 / dataRate
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMinDataRate() {
        this._assertOpen();
        if (this.data.minDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataRate;
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMaxDataRate() {
        this._assertOpen();
        if (this.data.maxDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataRate;
      }
      /**
       * This setting impacts how your motor decelerates and the amount of current that is available to your motor at any given moment.
       *
       *
       * For more information about `driveMode`, visit our [BLDCMotor API Guide](https://www.phidgets.com/docs/BLDCMotor_API_Guide#Drive_Mode)
       * @returns The drive type selection
       * @throws `PhidgetError`
       */
      getDriveMode() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 300:
          case 307:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.driveMode === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.driveMode;
      }
      /**
       * This setting impacts how your motor decelerates and the amount of current that is available to your motor at any given moment.
       *
       *
       * For more information about `driveMode`, visit our [BLDCMotor API Guide](https://www.phidgets.com/docs/BLDCMotor_API_Guide#Drive_Mode)
       * @throws `PhidgetError`
       * @param driveMode - The drive type selection
       */
      async setDriveMode(driveMode) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: driveMode
        });
        await bp.send(this._ch, 186);
      }
      /**
       * Enables the **failsafe** feature for the channel, with the specified **failsafe time**.
       *
       * Enabling the failsafe feature starts a recurring **failsafe timer** for the channel. Once the failsafe is enabled, the timer must be reset within the specified time or the channel will enter a **failsafe state**. For BLDC Motor channels, this will cut power to the motor, allowing it to coast (freewheel) instead. The failsafe timer can be reset by using any API call **_except_** for the following:
       *
       * *   `setRescaleFactor()`
       * *   `addPositionOffset()`
       * *   'get' API calls
       *
       * For more information about failsafe, visit our [Failsafe Guide](https://www.phidgets.com/docs/Failsafe_Guide).
       * @throws `PhidgetError`
       * @param failsafeTime - Failsafe timeout in milliseconds
       */
      async enableFailsafe(failsafeTime) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: failsafeTime
        });
        await bp.send(this._ch, 146);
      }
      /**
       * This setting allows you to choose whether motor will forcibly stop once it enters a **FAILSAFE** state.
       *
       * *   A setting of FALSE will simply stop applying power to the motor, allowing it to spin down naturally.
       * *   A setting of TRUE will apply braking up to the `failsafeCurrentLimit`, actively stopping the motor
       *
       *
       * For more information about `failsafeBrakingEnabled`, visit our [BLDCMotor API Guide](https://www.phidgets.com/docs/BLDCMotor_API_Guide#Failsafe_Braking_Enabled)
       * @returns Enables failsafe braking
       * @throws `PhidgetError`
       */
      getFailsafeBrakingEnabled() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 300:
          case 307:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.failsafeBrakingEnabled === 2) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return !!this.data.failsafeBrakingEnabled;
      }
      /**
       * This setting allows you to choose whether motor will forcibly stop once it enters a **FAILSAFE** state.
       *
       * *   A setting of FALSE will simply stop applying power to the motor, allowing it to spin down naturally.
       * *   A setting of TRUE will apply braking up to the `failsafeCurrentLimit`, actively stopping the motor
       *
       *
       * For more information about `failsafeBrakingEnabled`, visit our [BLDCMotor API Guide](https://www.phidgets.com/docs/BLDCMotor_API_Guide#Failsafe_Braking_Enabled)
       * @throws `PhidgetError`
       * @param failsafeBrakingEnabled - Enables failsafe braking
       */
      async setFailsafeBrakingEnabled(failsafeBrakingEnabled) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: failsafeBrakingEnabled ? 1 : 0
        });
        await bp.send(this._ch, 193);
      }
      /**
       * When the controller enters a **FAILSAFE** state, the controller will limit the current through the motor to the `failsafeCurrentLimit` value.
       *
       *
       * For more information about `failsafeCurrentLimit`, visit our [BLDCMotor API Guide](https://www.phidgets.com/docs/BLDCMotor_API_Guide#Failsafe_Current_Limit)
       * @returns The failsafe current limit value
       * @throws `PhidgetError`
       */
      getFailsafeCurrentLimit() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 300:
          case 307:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.failsafeCurrentLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.failsafeCurrentLimit;
      }
      /**
       * When the controller enters a **FAILSAFE** state, the controller will limit the current through the motor to the `failsafeCurrentLimit` value.
       *
       *
       * For more information about `failsafeCurrentLimit`, visit our [BLDCMotor API Guide](https://www.phidgets.com/docs/BLDCMotor_API_Guide#Failsafe_Current_Limit)
       * @throws `PhidgetError`
       * @param failsafeCurrentLimit - The failsafe current limit value
       */
      async setFailsafeCurrentLimit(failsafeCurrentLimit) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: failsafeCurrentLimit
        });
        await bp.send(this._ch, 192);
      }
      /**
       * The minimum value that `failsafeTime` can be set to when calling `enableFailsafe()`.
       * @returns The failsafe time
       * @throws `PhidgetError`
       */
      getMinFailsafeTime() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 290:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.minFailsafeTime === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minFailsafeTime;
      }
      /**
       * The maximum value that `failsafeTime` can be set to when calling `enableFailsafe()`.
       * @returns The failsafe time
       * @throws `PhidgetError`
       */
      getMaxFailsafeTime() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 290:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.maxFailsafeTime === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxFailsafeTime;
      }
      /**
       * The controller will attempt to measure the inductance of your motor when opened. This value is used to improve control of the motor.
       *
       * *   Set this value during the `Phidget.Attach` event to skip motor characterization (including the audible beeps). You can use a previously saved `inductance` value, or information from your motor's datasheet.
       *
       *
       * For more information about `inductance`, visit our [BLDCMotor API Guide](https://www.phidgets.com/docs/BLDCMotor_API_Guide#Motor_Inductance)
       * @returns The inductance of your motor
       * @throws `PhidgetError`
       */
      getInductance() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 300:
          case 307:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.inductance === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.inductance;
      }
      /**
       * The controller will attempt to measure the inductance of your motor when opened. This value is used to improve control of the motor.
       *
       * *   Set this value during the `Phidget.Attach` event to skip motor characterization (including the audible beeps). You can use a previously saved `inductance` value, or information from your motor's datasheet.
       *
       *
       * For more information about `inductance`, visit our [BLDCMotor API Guide](https://www.phidgets.com/docs/BLDCMotor_API_Guide#Motor_Inductance)
       * @throws `PhidgetError`
       * @param inductance - The inductance of your motor
       */
      async setInductance(inductance) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: inductance
        });
        await bp.send(this._ch, 184);
      }
      /**
       * The minimum value that `inductance` can be set to. See `inductance` for details.
       * @returns The motor inductance value
       * @throws `PhidgetError`
       */
      getMinInductance() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 300:
          case 307:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.minInductance === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minInductance;
      }
      /**
       * The maximum value that `inductance` can be set to. See `inductance` for details.
       * @returns The motor inductance value
       * @throws `PhidgetError`
       */
      getMaxInductance() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 300:
          case 307:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.maxInductance === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxInductance;
      }
      /**
       * Change the units of your parameters so that your application is more intuitive.
       *
       *
       * For more information about `rescaleFactor`, visit our [BLDCMotor API Guide](https://www.phidgets.com/docs/BLDCMotor_API_Guide#Rescale_Factor)
       * @returns The rescale factor value
       * @throws `PhidgetError`
       */
      getRescaleFactor() {
        this._assertOpen();
        if (this.data.rescaleFactor === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.rescaleFactor;
      }
      /**
       * Resets the failsafe timer, if one has been set. See `enableFailsafe()` for details.
       *
       * This function will fail if no failsafe timer has been set for the channel.
       * @throws `PhidgetError`
       */
      async resetFailsafe() {
        this._assertOpen();
        const bp = new BridgePacket();
        await bp.send(this._ch, 147);
      }
      /**
       * The `surgeCurrentLimit` allows for increased performance from your motor. The controller will limit the current through your motor to the `surgeCurrentLimit` briefly, then scale current down to the `currentLimit`.
       *
       * *   View `activeCurrentLimit` for information about what current limit the controller is actively following.
       *
       *
       * For more information about `surgeCurrentLimit`, visit our [BLDCMotor API Guide](https://www.phidgets.com/docs/BLDCMotor_API_Guide#Surge_Current_Limit)
       * @returns The surge current limit value
       * @throws `PhidgetError`
       */
      getSurgeCurrentLimit() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 300:
          case 307:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.surgeCurrentLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.surgeCurrentLimit;
      }
      /**
       * The `surgeCurrentLimit` allows for increased performance from your motor. The controller will limit the current through your motor to the `surgeCurrentLimit` briefly, then scale current down to the `currentLimit`.
       *
       * *   View `activeCurrentLimit` for information about what current limit the controller is actively following.
       *
       *
       * For more information about `surgeCurrentLimit`, visit our [BLDCMotor API Guide](https://www.phidgets.com/docs/BLDCMotor_API_Guide#Surge_Current_Limit)
       * @throws `PhidgetError`
       * @param surgeCurrentLimit - The surge current limit value
       */
      async setSurgeCurrentLimit(surgeCurrentLimit) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: surgeCurrentLimit
        });
        await bp.send(this._ch, 194);
      }
      /**
       * The minimum value that `surgeCurrentLimit` can be set to.
       * @returns The surge current value
       * @throws `PhidgetError`
       */
      getMinSurgeCurrentLimit() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 300:
          case 307:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.minSurgeCurrentLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minSurgeCurrentLimit;
      }
      /**
       * The maximum value that `surgeCurrentLimit` can be set to.
       * @returns The surge current value
       * @throws `PhidgetError`
       */
      getMaxSurgeCurrentLimit() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 300:
          case 307:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.maxSurgeCurrentLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxSurgeCurrentLimit;
      }
      /**
       * When a motor is not being actively driven forward or reverse, you can choose if the motor will be allowed to freely turn, or will resist being turned.
       *
       * *   A low `targetBrakingStrength` value corresponds to free wheeling, this will have the following effects:
       *     *   The motor will continue to rotate after the controller is no longer driving the motor (i.e. `velocity` is 0), due to inertia.
       *     *   The motor shaft will provide little resistance to being turned when it is stopped.
       * *   A higher `targetBrakingStrength` value will resist being turned, this will have the following effects:
       *     *   The motor will more stop more quickly if it is in motion and braking has been requested. It will fight against the rotation of the shaft.
       * *   Braking mode is enabled by setting the `velocity` to `minVelocity`
       * @returns The braking value
       * @throws `PhidgetError`
       */
      getTargetBrakingStrength() {
        this._assertOpen();
        if (this.data.targetBrakingStrength === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.targetBrakingStrength;
      }
      /**
       * When a motor is not being actively driven forward or reverse, you can choose if the motor will be allowed to freely turn, or will resist being turned.
       *
       * *   A low `targetBrakingStrength` value corresponds to free wheeling, this will have the following effects:
       *     *   The motor will continue to rotate after the controller is no longer driving the motor (i.e. `velocity` is 0), due to inertia.
       *     *   The motor shaft will provide little resistance to being turned when it is stopped.
       * *   A higher `targetBrakingStrength` value will resist being turned, this will have the following effects:
       *     *   The motor will more stop more quickly if it is in motion and braking has been requested. It will fight against the rotation of the shaft.
       * *   Braking mode is enabled by setting the `velocity` to `minVelocity`
       * @throws `PhidgetError`
       * @param targetBrakingStrength - The braking value
       */
      async setTargetBrakingStrength(targetBrakingStrength) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: targetBrakingStrength
        });
        await bp.send(this._ch, 44);
      }
      /**
       * The average voltage across the motor is based on the `targetVelocity` value.
       *
       * *   At a constant load, increasing the target velocity will increase the speed of the motor.
       * *   `targetVelocity` is bounded by -`maxVelocity` and +`maxVelocity`, where a sign change (±) is indicative of a direction change.
       * *   Setting `targetVelocity` to `minVelocity` will stop the motor. See `brakingEnabled` for more information on stopping the motor.
       *
       *
       * For more information about `targetVelocity`, visit our [BLDCMotor API Guide](https://www.phidgets.com/docs/BLDCMotor_API_Guide#Target_Velocity)
       * @returns The velocity value
       * @throws `PhidgetError`
       */
      getTargetVelocity() {
        this._assertOpen();
        if (this.data.targetVelocity === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.targetVelocity;
      }
      /**
       * The average voltage across the motor is based on the `targetVelocity` value.
       *
       * *   At a constant load, increasing the target velocity will increase the speed of the motor.
       * *   `targetVelocity` is bounded by -`maxVelocity` and +`maxVelocity`, where a sign change (±) is indicative of a direction change.
       * *   Setting `targetVelocity` to `minVelocity` will stop the motor. See `brakingEnabled` for more information on stopping the motor.
       *
       *
       * For more information about `targetVelocity`, visit our [BLDCMotor API Guide](https://www.phidgets.com/docs/BLDCMotor_API_Guide#Target_Velocity)
       * @throws `PhidgetError`
       * @param targetVelocity - The velocity value
       */
      async setTargetVelocity(targetVelocity) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: targetVelocity
        });
        await bp.send(this._ch, 55);
      }
      /**
       * The most recent `velocity` value that the controller has reported.
       *
       *
       * For more information about `velocity`, visit our [BLDCMotor API Guide](https://www.phidgets.com/docs/BLDCMotor_API_Guide#Velocity)
       * @returns The velocity value
       * @throws `PhidgetError`
       */
      getVelocity() {
        this._assertOpen();
        if (this.data.velocity === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.velocity;
      }
      /**
       * The minimum value that `targetVelocity` can be set to.
       *
       * *   Set the `targetVelocity` to `minVelocity` to stop the motor. See `brakingEnabled` for more information on stopping the motor.
       * *   `targetVelocity` is bounded by -`maxVelocity` and +`maxVelocity`, where a sign change (±) is indicative of a direction change.
       * @returns The velocity value
       * @throws `PhidgetError`
       */
      getMinVelocity() {
        this._assertOpen();
        if (this.data.minVelocity === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minVelocity;
      }
      /**
       * The maximum value that `targetVelocity` can be set to.
       *
       * *   `targetVelocity` is bounded by -`maxVelocity` and +`maxVelocity`, where a sign change (±) is indicative of a direction change.
       * @returns The velocity value
       * @throws `PhidgetError`
       */
      getMaxVelocity() {
        this._assertOpen();
        if (this.data.maxVelocity === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxVelocity;
      }
    }

    /** @public */
    class BLDCMotor extends BLDCMotorBase {
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 29:
            this.data.position = bp.getNumber(0);
            if (this._isAttachedDone && this.onPositionChange) {
              try {
                this.onPositionChange((this.data.position + this.data.positionOffset) * this.data.rescaleFactor);
              } catch (err) {
                logEventException(err);
              }
            }
            break;
          case 10:
            if (bp.entryCount > 1) this.data.dataInterval = bp.getNumber(1);else this.data.dataInterval = bp.getNumber(0);
            this._FIREPropertyChange("DataInterval");
            this._FIREPropertyChange("DataRate");
            break;
          case 196:
            this.data.currentLimit = bp.getNumber(0);
            this._FIREPropertyChange("CurrentLimit");
            break;
          case 185:
            {
              this.data.inductance = bp.getNumber(0);
              this._FIREPropertyChange('Inductance');
              break;
            }
          case 195:
            this.data.surgeCurrentLimit = bp.getNumber(0);
            this._FIREPropertyChange("SurgeCurrentLimit");
            break;
          case 197:
            {
              const activeCurrentLimit = bp.getNumber(0);
              if (this.data.activeCurrentLimit != activeCurrentLimit) {
                this.data.activeCurrentLimit = activeCurrentLimit;
                this._FIREPropertyChange("ActiveCurrentLimit");
              }
              break;
            }
          default:
            super._bridgeInput(bp);
            break;
        }
      }
      /** @internal */
      async _setDefaults() {
        try {
          await super._setDefaults();
        } catch (err) {
          if (err instanceof PhidgetError) {
            switch (err.errorCode) {
              case exports.ErrorCode.FAILSAFE:
                err.message = "External stop procedure initiated.";
                break;
              case exports.ErrorCode.BAD_POWER:
                err.message = "Your power supply voltage is too high for the motor controller to begin operation.";
                break;
              case exports.ErrorCode.POWER_CYCLE:
                err.message = "An overvoltage fault has triggered. Power your device off and on to resume operation. We recommend a PowerGuard Phidget to prevent this in future.";
                break;
              case exports.ErrorCode.HALLSENSOR:
                err.message = "The hall sensor of your BLDC motor is not reporting a valid input. The cable is likely damaged or unplugged.";
                break;
              case exports.ErrorCode.BADCURRENT:
                err.message = "The current sensor is seeing an unacceptable offset in its readings. Move the controller away from magnetic fields and try again.";
                break;
            }
          }
          throw err;
        }
      }
      setRescaleFactor(rescaleFactor) {
        this._assertOpen();
        if (rescaleFactor === 0) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT);
        this.data.rescaleFactor = rescaleFactor;
      }
      getPosition() {
        this._assertOpen();
        if (this.data.position === 9223372036854776000) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return (this.data.position + this.data.positionOffset) * this.data.rescaleFactor;
      }
      getMinPosition() {
        this._assertOpen();
        if (this.data.minPosition === 9223372036854776000) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return (this.data.minPosition + this.data.positionOffset) * this.data.rescaleFactor;
      }
      getMaxPosition() {
        this._assertOpen();
        if (this.data.maxPosition === 9223372036854776000) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return (this.data.maxPosition + this.data.positionOffset) * this.data.rescaleFactor;
      }
      addPositionOffset(positionOffset) {
        this._assertOpen();
        this.data.positionOffset += Math.round(positionOffset / this.data.rescaleFactor);
      }
      async setStallVelocity(stallVelocity) {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 290:
          case 293:
          case 296:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        const calcVelocity = stallVelocity / this.data.rescaleFactor;
        if (calcVelocity < this.data.minStallVelocity || calcVelocity > this.data.maxStallVelocity) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Value must be in range: " + this.minStallVelocity + " - " + this.maxStallVelocity + ".");
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: calcVelocity
        });
        await bp.send(this._ch, 141);
      }
      getStallVelocity() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 290:
          case 293:
          case 296:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.stallVelocity === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.stallVelocity * this.data.rescaleFactor;
      }
      getMinStallVelocity() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 290:
          case 293:
          case 296:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.minStallVelocity === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minStallVelocity * this.data.rescaleFactor;
      }
      getMaxStallVelocity() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 290:
          case 293:
          case 296:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.maxStallVelocity === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxStallVelocity * this.data.rescaleFactor;
      }
      getBrakingEnabled() {
        this._assertOpen();
        if (this.data.targetBrakingStrength === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.targetBrakingStrength == 0 ? false : true;
      }
      async setBrakingEnabled(brakingEnabled) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: brakingEnabled ? 1 : 0
        });
        await bp.send(this._ch, 44);
      }
    }

    /**
     * The Capacitive Touch class gathers input data from capacitive buttons and sliders on Phidget boards.
     * @public
     */
    class CapacitiveTouchBase extends PhidgetChannel {
      /** @internal */
      data;
      onTouch = null;
      /** @internal */
      _gotTouchErrorEvent;
      onTouchEnd = null;
      /** @internal */
      _gotTouchEndErrorEvent;
      constructor(ch) {
        super(ch);
        this._class = exports.ChannelClass.CAPACITIVE_TOUCH;
        this.name = "CapacitiveTouch";
        this.data = this._initData();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 54:
            if (bp.entryCount > 1) this.data.dataInterval = bp.entries[1].v;else this.data.dataInterval = bp.entries[0].v;
            this._FIREPropertyChange('DataInterval', bp);
            this._FIREPropertyChange('DataRate', bp);
            break;
          case 66:
            this.data.sensitivity = bp.entries[0].v;
            this._FIREPropertyChange('Sensitivity', bp);
            break;
          case 46:
            this.data.touchValueChangeTrigger = bp.entries[0].v;
            this._FIREPropertyChange('TouchValueChangeTrigger', bp);
            break;
          case 96:
            {
              this.data.touchValue = bp.entries[0].v;
              if (this._isAttachedDone && this.onTouch) {
                try {
                  this.onTouch(this.data.touchValue);
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          case 137:
            {
              if (this._isAttachedDone && this.onTouchEnd) {
                try {
                  this.onTouchEnd();
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          default:
            throw new PhidgetError(exports.ErrorCode.INVALID_PACKET, "Unsupported bridge packet: 0x" + bp.vpkt.toString(16));
        }
      }
      /** @internal */
      _initData() {
        return {
          touchValueChangeTrigger: 1e+300,
          minTouchValueChangeTrigger: 1e+300,
          maxTouchValueChangeTrigger: 1e+300,
          dataInterval: 1e+300,
          minDataInterval: 4294967295,
          maxDataInterval: 4294967295,
          minDataRate: 1e+300,
          maxDataRate: 1e+300,
          sensitivity: 1e+300,
          minSensitivity: 1e+300,
          maxSensitivity: 1e+300,
          maxTouchValue: 1e+300,
          minTouchValue: 1e+300,
          touchValue: 1e+300,
          isTouched: 2
        };
      }
      /** @internal */
      _initAfterOpen() {}
      /** @internal */
      async _setDefaults() {}
      /** @internal */
      _hasInitialState() {
        return true;
      }
      /** @internal */
      _fireInitialEvents() {}
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `Touch` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between `Touch` events can also be affected by the `touchValueChangeTrigger`.
       * @throws `PhidgetError`
       */
      get dataInterval() {
        return this.getDataInterval();
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get minDataInterval() {
        return this.getMinDataInterval();
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataInterval() {
        return this.getMaxDataInterval();
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       */
      get dataRate() {
        return this.getDataRate();
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get minDataRate() {
        return this.getMinDataRate();
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataRate() {
        return this.getMaxDataRate();
      }
      /**
       * Determines the sensitivity of all capacitive regions on the device.
       *
       * *   Higher values result in greater touch sensitivity.
       * *   The sensitivity value is bounded by `minSensitivity` and `maxSensitivity`.
       * @throws `PhidgetError`
       */
      get sensitivity() {
        return this.getSensitivity();
      }
      /**
       * The minimum value that `sensitivity` can be set to.
       * @throws `PhidgetError`
       */
      get minSensitivity() {
        return this.getMinSensitivity();
      }
      /**
       * The maximum value that `sensitivity` can be set to.
       * @throws `PhidgetError`
       */
      get maxSensitivity() {
        return this.getMaxSensitivity();
      }
      /**
       * The most recent touch state that the channel has reported.
       *
       * *   This will be 0 or 1
       *
       * *   0 is not touched
       * *   1 is touched
       * @throws `PhidgetError`
       */
      get isTouched() {
        return this.getIsTouched();
      }
      /**
       * The most recent touch value that the channel has reported.
       *
       * *   This will be 0 or 1 for button-type inputs, or a ratio between 0-1 for axis-type inputs.
       * *   This value is bounded by `minTouchValue` and `maxTouchValue`
       * *   The value is not reset when the touch ends
       * @throws `PhidgetError`
       */
      get touchValue() {
        return this.getTouchValue();
      }
      /**
       * The minimum value the `Touch` event will report.
       * @throws `PhidgetError`
       */
      get minTouchValue() {
        return this.getMinTouchValue();
      }
      /**
       * The maximum value the `Touch` event will report.
       * @throws `PhidgetError`
       */
      get maxTouchValue() {
        return this.getMaxTouchValue();
      }
      /**
       * The channel will not issue a `Touch` event until the touch value has changed by the amount specified by the `touchValueChangeTrigger`.
       *
       * *   Setting the `touchValueChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @throws `PhidgetError`
       */
      get touchValueChangeTrigger() {
        return this.getTouchValueChangeTrigger();
      }
      /**
       * The minimum value that `touchValueChangeTrigger` can be set to.
       * @throws `PhidgetError`
       */
      get minTouchValueChangeTrigger() {
        return this.getMinTouchValueChangeTrigger();
      }
      /**
       * The maximum value that `touchValueChangeTrigger` can be set to.
       * @throws `PhidgetError`
       */
      get maxTouchValueChangeTrigger() {
        return this.getMaxTouchValueChangeTrigger();
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `Touch` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between `Touch` events can also be affected by the `touchValueChangeTrigger`.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getDataInterval() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.dataInterval;
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `Touch` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between `Touch` events can also be affected by the `touchValueChangeTrigger`.
       * @throws `PhidgetError`
       * @param dataInterval - The data interval value
       */
      async setDataInterval(dataInterval) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: dataInterval
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @returns The minimum data interval value
       * @throws `PhidgetError`
       */
      getMinDataInterval() {
        this._assertOpen();
        if (this.data.minDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataInterval;
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @returns The maximum data interval value
       * @throws `PhidgetError`
       */
      getMaxDataInterval() {
        this._assertOpen();
        if (this.data.maxDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @returns The data rate for the channel
       * @throws `PhidgetError`
       */
      getDataRate() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return 1000.0 / this.data.dataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       * @param dataRate - The data rate for the channel
       */
      async setDataRate(dataRate) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: Math.round(1000.0 / dataRate)
        });
        bp.set({
          name: "1",
          type: "g",
          value: 1000.0 / dataRate
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMinDataRate() {
        this._assertOpen();
        if (this.data.minDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataRate;
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMaxDataRate() {
        this._assertOpen();
        if (this.data.maxDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataRate;
      }
      /**
       * The most recent touch state that the channel has reported.
       *
       * *   This will be 0 or 1
       *
       * *   0 is not touched
       * *   1 is touched
       * @returns The touched state
       * @throws `PhidgetError`
       */
      getIsTouched() {
        this._assertOpen();
        if (this.data.isTouched === 2) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return !!this.data.isTouched;
      }
      /**
       * Determines the sensitivity of all capacitive regions on the device.
       *
       * *   Higher values result in greater touch sensitivity.
       * *   The sensitivity value is bounded by `minSensitivity` and `maxSensitivity`.
       * @returns The sensitivity value
       * @throws `PhidgetError`
       */
      getSensitivity() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 42:
          case 43:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.sensitivity === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.sensitivity;
      }
      /**
       * Determines the sensitivity of all capacitive regions on the device.
       *
       * *   Higher values result in greater touch sensitivity.
       * *   The sensitivity value is bounded by `minSensitivity` and `maxSensitivity`.
       * @throws `PhidgetError`
       * @param sensitivity - The sensitivity value
       */
      async setSensitivity(sensitivity) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: sensitivity
        });
        await bp.send(this._ch, 66);
      }
      /**
       * The minimum value that `sensitivity` can be set to.
       * @returns The minimum sensitivity value
       * @throws `PhidgetError`
       */
      getMinSensitivity() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 42:
          case 43:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.minSensitivity === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minSensitivity;
      }
      /**
       * The maximum value that `sensitivity` can be set to.
       * @returns The maximum sensitivity value
       * @throws `PhidgetError`
       */
      getMaxSensitivity() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 42:
          case 43:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.maxSensitivity === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxSensitivity;
      }
      /**
       * The most recent touch value that the channel has reported.
       *
       * *   This will be 0 or 1 for button-type inputs, or a ratio between 0-1 for axis-type inputs.
       * *   This value is bounded by `minTouchValue` and `maxTouchValue`
       * *   The value is not reset when the touch ends
       * @returns The touch input value
       * @throws `PhidgetError`
       */
      getTouchValue() {
        this._assertOpen();
        if (this.data.touchValue === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.touchValue;
      }
      /**
       * The minimum value the `Touch` event will report.
       * @returns The minimum touch input value
       * @throws `PhidgetError`
       */
      getMinTouchValue() {
        this._assertOpen();
        if (this.data.minTouchValue === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minTouchValue;
      }
      /**
       * The maximum value the `Touch` event will report.
       * @returns The maximum touch input value
       * @throws `PhidgetError`
       */
      getMaxTouchValue() {
        this._assertOpen();
        if (this.data.maxTouchValue === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxTouchValue;
      }
      /**
       * The channel will not issue a `Touch` event until the touch value has changed by the amount specified by the `touchValueChangeTrigger`.
       *
       * *   Setting the `touchValueChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getTouchValueChangeTrigger() {
        this._assertOpen();
        if (this.data.touchValueChangeTrigger === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.touchValueChangeTrigger;
      }
      /**
       * The channel will not issue a `Touch` event until the touch value has changed by the amount specified by the `touchValueChangeTrigger`.
       *
       * *   Setting the `touchValueChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @throws `PhidgetError`
       * @param touchValueChangeTrigger - The change trigger value
       */
      async setTouchValueChangeTrigger(touchValueChangeTrigger) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: touchValueChangeTrigger
        });
        await bp.send(this._ch, 46);
      }
      /**
       * The minimum value that `touchValueChangeTrigger` can be set to.
       * @returns The minimum change trigger value
       * @throws `PhidgetError`
       */
      getMinTouchValueChangeTrigger() {
        this._assertOpen();
        if (this.data.minTouchValueChangeTrigger === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minTouchValueChangeTrigger;
      }
      /**
       * The maximum value that `touchValueChangeTrigger` can be set to.
       * @returns The maximum change trigger value
       * @throws `PhidgetError`
       */
      getMaxTouchValueChangeTrigger() {
        this._assertOpen();
        if (this.data.maxTouchValueChangeTrigger === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxTouchValueChangeTrigger;
      }
    }

    /** @public */
    class CapacitiveTouch extends CapacitiveTouchBase {
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 96:
            this.data.isTouched = 1;
            super._bridgeInput(bp);
            break;
          case 137:
            this.data.isTouched = 0;
            super._bridgeInput(bp);
            break;
          default:
            super._bridgeInput(bp);
            break;
        }
      }
    }

    /**
     * The Current Input class is used to measure current flowing through the Phidget from outside sources.
     *
     * This class may be used on a simple current sensor, or sometimes on a more complex Phidget that measures the amount of current flowing through an attached device, such as a motor controller, for diagnostic or control purposes.
     * @public
     */
    class CurrentInputBase extends PhidgetChannel {
      /** @internal */
      data;
      onCurrentChange = null;
      /** @internal */
      _gotCurrentChangeErrorEvent;
      constructor(ch) {
        super(ch);
        this._class = exports.ChannelClass.CURRENT_INPUT;
        this.name = "CurrentInput";
        this.data = this._initData();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 46:
            this.data.currentChangeTrigger = bp.entries[0].v;
            this._FIREPropertyChange('CurrentChangeTrigger', bp);
            break;
          case 54:
            if (bp.entryCount > 1) this.data.dataInterval = bp.entries[1].v;else this.data.dataInterval = bp.entries[0].v;
            this._FIREPropertyChange('DataInterval', bp);
            this._FIREPropertyChange('DataRate', bp);
            break;
          case 74:
            this.data.powerSupply = bp.entries[0].v;
            this._FIREPropertyChange('PowerSupply', bp);
            break;
          case 8:
            {
              this.data.current = bp.entries[0].v;
              if (this._isAttachedDone && this.onCurrentChange) {
                try {
                  this.onCurrentChange(this.data.current);
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          default:
            throw new PhidgetError(exports.ErrorCode.INVALID_PACKET, "Unsupported bridge packet: 0x" + bp.vpkt.toString(16));
        }
      }
      /** @internal */
      _initData() {
        return {
          dataInterval: 1e+300,
          minDataInterval: 4294967295,
          maxDataInterval: 4294967295,
          minDataRate: 1e+300,
          maxDataRate: 1e+300,
          maxCurrent: 1e+300,
          maxCurrentChangeTrigger: 1e+300,
          minCurrent: 1e+300,
          minCurrentChangeTrigger: 1e+300,
          current: 1e+300,
          currentChangeTrigger: 1e+300,
          powerSupply: 2147483647
        };
      }
      /** @internal */
      _initAfterOpen() {}
      /** @internal */
      async _setDefaults() {}
      /** @internal */
      _hasInitialState() {
        return true;
      }
      /** @internal */
      _fireInitialEvents() {}
      /**
       * The most recent current value that the channel has reported.
       *
       * *   This value will always be between `minCurrent` and `maxCurrent`.
       * @throws `PhidgetError`
       */
      get current() {
        return this.getCurrent();
      }
      /**
       * The minimum value the `CurrentChange` event will report.
       * @throws `PhidgetError`
       */
      get minCurrent() {
        return this.getMinCurrent();
      }
      /**
       * The maximum value the `CurrentChange` event will report.
       * @throws `PhidgetError`
       */
      get maxCurrent() {
        return this.getMaxCurrent();
      }
      /**
       * The channel will not issue a `CurrentChange` event until the current value has changed by the amount specified by the `currentChangeTrigger`.
       *
       * *   Setting the `currentChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @throws `PhidgetError`
       */
      get currentChangeTrigger() {
        return this.getCurrentChangeTrigger();
      }
      /**
       * The minimum value that `currentChangeTrigger` can be set to.
       * @throws `PhidgetError`
       */
      get minCurrentChangeTrigger() {
        return this.getMinCurrentChangeTrigger();
      }
      /**
       * The maximum value that `currentChangeTrigger` can be set to.
       * @throws `PhidgetError`
       */
      get maxCurrentChangeTrigger() {
        return this.getMaxCurrentChangeTrigger();
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `CurrentChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between `CurrentChange` events can also be affected by the `currentChangeTrigger`.
       * @throws `PhidgetError`
       */
      get dataInterval() {
        return this.getDataInterval();
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get minDataInterval() {
        return this.getMinDataInterval();
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataInterval() {
        return this.getMaxDataInterval();
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       */
      get dataRate() {
        return this.getDataRate();
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get minDataRate() {
        return this.getMinDataRate();
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataRate() {
        return this.getMaxDataRate();
      }
      /**
       * Choose the power supply voltage.
       *
       * *   Set this to the voltage specified in the attached sensor's data sheet to power it.
       * *   Set to `phidget22.PowerSupply.OFF` to turn off the supply to save power.
       * @throws `PhidgetError`
       */
      get powerSupply() {
        return this.getPowerSupply();
      }
      /**
       * The most recent current value that the channel has reported.
       *
       * *   This value will always be between `minCurrent` and `maxCurrent`.
       * @returns The current value
       * @throws `PhidgetError`
       */
      getCurrent() {
        this._assertOpen();
        if (this.data.current === 1e+300 || Number.isNaN(this.data.current)) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        if (this.data.current > this.data.maxCurrent) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE_HIGH);
        if (this.data.current < this.data.minCurrent) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE_LOW);
        return this.data.current;
      }
      /**
       * The minimum value the `CurrentChange` event will report.
       * @returns The current value
       * @throws `PhidgetError`
       */
      getMinCurrent() {
        this._assertOpen();
        if (this.data.minCurrent === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minCurrent;
      }
      /**
       * The maximum value the `CurrentChange` event will report.
       * @returns The current value
       * @throws `PhidgetError`
       */
      getMaxCurrent() {
        this._assertOpen();
        if (this.data.maxCurrent === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxCurrent;
      }
      /**
       * The channel will not issue a `CurrentChange` event until the current value has changed by the amount specified by the `currentChangeTrigger`.
       *
       * *   Setting the `currentChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getCurrentChangeTrigger() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 345:
          case 347:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.currentChangeTrigger === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.currentChangeTrigger;
      }
      /**
       * The channel will not issue a `CurrentChange` event until the current value has changed by the amount specified by the `currentChangeTrigger`.
       *
       * *   Setting the `currentChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @throws `PhidgetError`
       * @param currentChangeTrigger - The change trigger value
       */
      async setCurrentChangeTrigger(currentChangeTrigger) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: currentChangeTrigger
        });
        await bp.send(this._ch, 46);
      }
      /**
       * The minimum value that `currentChangeTrigger` can be set to.
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getMinCurrentChangeTrigger() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 345:
          case 347:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.minCurrentChangeTrigger === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minCurrentChangeTrigger;
      }
      /**
       * The maximum value that `currentChangeTrigger` can be set to.
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getMaxCurrentChangeTrigger() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 345:
          case 347:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.maxCurrentChangeTrigger === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxCurrentChangeTrigger;
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `CurrentChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between `CurrentChange` events can also be affected by the `currentChangeTrigger`.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getDataInterval() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.dataInterval;
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `CurrentChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between `CurrentChange` events can also be affected by the `currentChangeTrigger`.
       * @throws `PhidgetError`
       * @param dataInterval - The data interval value
       */
      async setDataInterval(dataInterval) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: dataInterval
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMinDataInterval() {
        this._assertOpen();
        if (this.data.minDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataInterval;
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMaxDataInterval() {
        this._assertOpen();
        if (this.data.maxDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @returns The data rate for the channel
       * @throws `PhidgetError`
       */
      getDataRate() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return 1000.0 / this.data.dataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       * @param dataRate - The data rate for the channel
       */
      async setDataRate(dataRate) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: Math.round(1000.0 / dataRate)
        });
        bp.set({
          name: "1",
          type: "g",
          value: 1000.0 / dataRate
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMinDataRate() {
        this._assertOpen();
        if (this.data.minDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataRate;
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMaxDataRate() {
        this._assertOpen();
        if (this.data.maxDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataRate;
      }
      /**
       * Choose the power supply voltage.
       *
       * *   Set this to the voltage specified in the attached sensor's data sheet to power it.
       * *   Set to `phidget22.PowerSupply.OFF` to turn off the supply to save power.
       * @returns The power supply value
       * @throws `PhidgetError`
       */
      getPowerSupply() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 233:
          case 237:
          case 241:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.powerSupply === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.powerSupply;
      }
      /**
       * Choose the power supply voltage.
       *
       * *   Set this to the voltage specified in the attached sensor's data sheet to power it.
       * *   Set to `phidget22.PowerSupply.OFF` to turn off the supply to save power.
       * @throws `PhidgetError`
       * @param powerSupply - The power supply value
       */
      async setPowerSupply(powerSupply) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: powerSupply
        });
        await bp.send(this._ch, 74);
      }
    }

    /** @public */
    class CurrentInput extends CurrentInputBase {
      /** @internal */
      _errorHandler(code) {
        switch (code) {
          case exports.ErrorEventCode.SATURATION:
            this.data.current = 1e+300;
            this._gotCurrentChangeErrorEvent = true;
            break;
        }
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 181:
            this.data.powerSupply = bp.entries[0].v;
            this._FIREPropertyChange('PowerSupply', bp);
            break;
          default:
            super._bridgeInput(bp);
            break;
        }
      }
    }

    /**
     * The Data Adapter class is used to interface third party devices and microcontrollers with Phidgets.
     * @public
     */
    class DataAdapterBase extends PhidgetChannel {
      /** @internal */
      data;
      constructor(ch) {
        super(ch);
        this._class = exports.ChannelClass.DATA_ADAPTER;
        this.name = "DataAdapter";
        this.data = this._initData();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 168:
            this.data.dataAdapterVoltage = bp.entries[0].v;
            this._FIREPropertyChange('DataAdapterVoltage', bp);
            break;
          case 160:
            this.data.dataBits = bp.entries[0].v;
            this._FIREPropertyChange('DataBits', bp);
            break;
          case 165:
            this.data.endianness = bp.entries[0].v;
            this._FIREPropertyChange('Endianness', bp);
            break;
          case 157:
            this.data.frequency = bp.entries[0].v;
            this._FIREPropertyChange('Frequency', bp);
            break;
          case 208:
            break;
          case 118:
            break;
          case 169:
            break;
          case 199:
            this.data.SPIChipSelect = bp.entries[0].v;
            this._FIREPropertyChange('SPIChipSelect', bp);
            break;
          case 163:
            this.data.SPIMode = bp.entries[0].v;
            this._FIREPropertyChange('SPIMode', bp);
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.INVALID_PACKET, "Unsupported bridge packet: 0x" + bp.vpkt.toString(16));
        }
      }
      /** @internal */
      _initData() {
        return {
          lastData: new Array(8192).fill(255),
          lastDataIndex: 0,
          eventData: new Array(8193).fill(255),
          eventDataLen: 0,
          eventDataError: 0,
          lastDataLen: 0,
          lastDataError: 0,
          lastDataRead: 0,
          endOfLine: null,
          maxSendPacketLength: 4294967295,
          maxReceivePacketLength: 4294967295,
          frequency: 2147483647,
          dataBits: 4294967295,
          minDataBits: 4294967295,
          maxDataBits: 4294967295,
          SPIMode: 2147483647,
          SPIChipSelect: 2147483647,
          endianness: 2147483647,
          dataAdapterVoltage: 2147483647
        };
      }
      /** @internal */
      _initAfterOpen() {}
      /** @internal */
      async _setDefaults() {}
      /** @internal */
      _hasInitialState() {
        return true;
      }
      /** @internal */
      _fireInitialEvents() {}
      /**
       * The voltage used to communicate with and power the external device.
       * @throws `PhidgetError`
       */
      get dataAdapterVoltage() {
        return this.getDataAdapterVoltage();
      }
      /**
       * Configures the number of data bits used for communication. Refer to the documentation for the device you are communicating with.
       * @throws `PhidgetError`
       */
      get dataBits() {
        return this.getDataBits();
      }
      /**
       * The minimum number of data bits
       * @throws `PhidgetError`
       */
      get minDataBits() {
        return this.getMinDataBits();
      }
      /**
       * The maximum number of data bits
       * @throws `PhidgetError`
       */
      get maxDataBits() {
        return this.getMaxDataBits();
      }
      /**
       * Configures endianness of each byte.
       * @throws `PhidgetError`
       */
      get endianness() {
        return this.getEndianness();
      }
      /**
       * The rate at which data is transmitted over the communication lines in bits per second.
       * @throws `PhidgetError`
       */
      get frequency() {
        return this.getFrequency();
      }
      /**
       * The maximum length of a packet that can be received in bytes.
       * @throws `PhidgetError`
       */
      get maxReceivePacketLength() {
        return this.getMaxReceivePacketLength();
      }
      /**
       * The maximum length of a packet that can be sent in bytes.
       * @throws `PhidgetError`
       */
      get maxSendPacketLength() {
        return this.getMaxSendPacketLength();
      }
      /**
       * Configures functionality of the SPI chip select pin
       * @throws `PhidgetError`
       */
      get SPIChipSelect() {
        return this.getSPIChipSelect();
      }
      /**
       * Configures SCLK polarity and phase.
       * @throws `PhidgetError`
       */
      get SPIMode() {
        return this.getSPIMode();
      }
      /**
       * The voltage used to communicate with and power the external device.
       * @returns The voltage value
       * @throws `PhidgetError`
       */
      getDataAdapterVoltage() {
        this._assertOpen();
        if (this.data.dataAdapterVoltage === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.dataAdapterVoltage;
      }
      /**
       * The voltage used to communicate with and power the external device.
       * @throws `PhidgetError`
       * @param dataAdapterVoltage - The voltage value
       */
      async setDataAdapterVoltage(dataAdapterVoltage) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: dataAdapterVoltage
        });
        await bp.send(this._ch, 168);
      }
      /**
       * Configures the number of data bits used for communication. Refer to the documentation for the device you are communicating with.
       * @returns The number of data bits
       * @throws `PhidgetError`
       */
      getDataBits() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 201:
          case 204:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.dataBits === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.dataBits;
      }
      /**
       * Configures the number of data bits used for communication. Refer to the documentation for the device you are communicating with.
       * @throws `PhidgetError`
       * @param dataBits - The number of data bits
       */
      async setDataBits(dataBits) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: dataBits
        });
        await bp.send(this._ch, 160);
      }
      /**
       * The minimum number of data bits
       * @returns The number of data bits
       * @throws `PhidgetError`
       */
      getMinDataBits() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 201:
          case 204:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.minDataBits === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataBits;
      }
      /**
       * The maximum number of data bits
       * @returns The number of data bits
       * @throws `PhidgetError`
       */
      getMaxDataBits() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 201:
          case 204:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.maxDataBits === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataBits;
      }
      /**
       * Configures endianness of each byte.
       * @returns The endianness of the data bytes.
       * @throws `PhidgetError`
       */
      getEndianness() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 201:
          case 204:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.endianness === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.endianness;
      }
      /**
       * Configures endianness of each byte.
       * @throws `PhidgetError`
       * @param endianness - The endianness of the data bytes.
       */
      async setEndianness(endianness) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: endianness
        });
        await bp.send(this._ch, 165);
      }
      /**
       * The rate at which data is transmitted over the communication lines in bits per second.
       * @returns The communication frequency to use for future data transfers.
       * @throws `PhidgetError`
       */
      getFrequency() {
        this._assertOpen();
        if (this.data.frequency === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.frequency;
      }
      /**
       * The rate at which data is transmitted over the communication lines in bits per second.
       * @throws `PhidgetError`
       * @param frequency - The communication frequency to use for future data transfers.
       */
      async setFrequency(frequency) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: frequency
        });
        await bp.send(this._ch, 157);
      }
      /**
       * The maximum length of a packet that can be received in bytes.
       * @returns The maximum length of a received packet.
       * @throws `PhidgetError`
       */
      getMaxReceivePacketLength() {
        this._assertOpen();
        if (this.data.maxReceivePacketLength === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxReceivePacketLength;
      }
      /**
       * The maximum length of a packet that can be sent in bytes.
       * @returns The maximum length of a sent packet.
       * @throws `PhidgetError`
       */
      getMaxSendPacketLength() {
        this._assertOpen();
        if (this.data.maxSendPacketLength === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxSendPacketLength;
      }
      /**
       * Configures functionality of the SPI chip select pin
       * @returns The SPI chip select polarity.
       * @throws `PhidgetError`
       */
      getSPIChipSelect() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 201:
          case 204:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.SPIChipSelect === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.SPIChipSelect;
      }
      /**
       * Configures functionality of the SPI chip select pin
       * @throws `PhidgetError`
       * @param SPIChipSelect - The SPI chip select polarity.
       */
      async setSPIChipSelect(SPIChipSelect) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: SPIChipSelect
        });
        await bp.send(this._ch, 199);
      }
      /**
       * Configures SCLK polarity and phase.
       * @returns The SPI mode.
       * @throws `PhidgetError`
       */
      getSPIMode() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 201:
          case 204:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.SPIMode === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.SPIMode;
      }
      /**
       * Configures SCLK polarity and phase.
       * @throws `PhidgetError`
       * @param SPIMode - The SPI mode.
       */
      async setSPIMode(SPIMode) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: SPIMode
        });
        await bp.send(this._ch, 163);
      }
    }

    /** @public */
    class DataAdapter extends DataAdapterBase {
      /** @internal */
      _transactionLock;
      /** @internal */
      _private;
      constructor(ch) {
        super(ch);
        this._transactionLock = new PhidgetLock();
      }
      /** @internal */
      _initAfterOpen() {
        super._initAfterOpen();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 202:
            if (this.data.dataAdapterVoltage !== bp.entries[0].v) {
              this.data.dataAdapterVoltage = bp.entries[0].v;
              this._FIREPropertyChange('DataAdapterVoltage', bp);
            }
            break;
          default:
            super._bridgeInput(bp);
            break;
        }
      }
      async sendPacket(data) {
        this._assertOpen();
        if (data.length === 0) return Promise.resolve();
        if (data.length > this.data.maxSendPacketLength) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Send packet length must be less than " + this.data.maxSendPacketLength);
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: 'R',
          value: data instanceof Uint8Array ? data : new Uint8Array(data)
        });
        await bp.send(this._ch, 118);
      }
      async sendPacketWaitResponse(sendData) {
        this._assertOpen();
        let maxSendReceiveLength;
        const bp = new BridgePacket();
        switch (this._ch?.chDef.uid) {
          case 201:
          case 204:
            maxSendReceiveLength = this.data.maxSendPacketLength;
            break;
          case 207:
          case 210:
            maxSendReceiveLength = this.data.maxReceivePacketLength;
            if (sendData.length === 0) return Promise.resolve(new Uint8Array());
            break;
          default:
            maxSendReceiveLength = this.data.maxReceivePacketLength;
            break;
        }
        if (sendData.length > maxSendReceiveLength) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Send/receive packet length must be less than " + maxSendReceiveLength);
        bp.set({
          name: "0",
          type: 'R',
          value: sendData instanceof Uint8Array ? sendData : new Uint8Array(sendData)
        });
        return await bp.send(this._ch, 169);
      }
      i2cSendReceive(address, data, receiveLength = 0) {
        this._assertOpen();
        if (address < 0 || address > 127) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Address must be within the range of 0x00 and 0xFF");
        if (data.length > this.data.maxSendPacketLength) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Send packet length must be less than " + this.data.maxSendPacketLength);
        if (receiveLength > this.data.maxReceivePacketLength) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Specified receive packet length must be less than " + this.data.maxReceivePacketLength);
        let formatString;
        if (data.length === 0 && receiveLength === 0) return Promise.resolve(new Uint8Array());else if (receiveLength === 0) formatString = `sT${data.length}p`;else if (data.length === 0) formatString = `sR${receiveLength}p`;else formatString = `sT${data.length}sR${receiveLength}p`;
        return this.i2cComplexTransaction(address, formatString, data);
      }
      async i2cComplexTransaction(address, i2cPacketString, data) {
        this._assertOpen();
        const bp = new BridgePacket();
        if (address < 0 || address > 127) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Address must be within the range of 0x00 and 0xFF");
        if (data.length > this.data.maxSendPacketLength) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Send packet length must be less than " + this.data.maxSendPacketLength);
        bp.set({
          name: "0",
          type: 'R',
          value: data instanceof Uint8Array ? data : new Uint8Array(data)
        });
        bp.set({
          name: "1",
          type: "u",
          value: address
        });
        bp.set({
          name: "2",
          type: "s",
          value: i2cPacketString
        });
        return await bp.send(this._ch, 208);
      }
    }

    /**
     * The DC Motor class controls the power applied to attached DC motors to affect its speed and direction. It can also contain various other control and monitoring functions that aid in the control of DC motors.
     * @public
     */
    class DCMotorBase extends PhidgetChannel {
      /** @internal */
      data;
      onBrakingStrengthChange = null;
      /** @internal */
      _gotBrakingStrengthChangeErrorEvent;
      onVelocityUpdate = null;
      /** @internal */
      _gotVelocityUpdateErrorEvent;
      onBackEMFChange = null;
      /** @internal */
      _gotBackEMFChangeErrorEvent;
      constructor(ch) {
        super(ch);
        this._class = exports.ChannelClass.DC_MOTOR;
        this.name = "DCMotor";
        this.data = this._initData();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 40:
            this.data.acceleration = bp.entries[0].v;
            this._FIREPropertyChange('Acceleration', bp);
            break;
          case 42:
            this.data.backEMFSensingState = bp.entries[0].v;
            this._FIREPropertyChange('BackEMFSensingState', bp);
            break;
          case 51:
            this.data.currentLimit = bp.entries[0].v;
            this._FIREPropertyChange('CurrentLimit', bp);
            break;
          case 119:
            this.data.currentRegulatorGain = bp.entries[0].v;
            this._FIREPropertyChange('CurrentRegulatorGain', bp);
            break;
          case 54:
            if (bp.entryCount > 1) this.data.dataInterval = bp.entries[1].v;else this.data.dataInterval = bp.entries[0].v;
            this._FIREPropertyChange('DataInterval', bp);
            this._FIREPropertyChange('DataRate', bp);
            break;
          case 186:
            this.data.driveMode = bp.entries[0].v;
            this._FIREPropertyChange('DriveMode', bp);
            break;
          case 146:
            break;
          case 193:
            this.data.failsafeBrakingEnabled = bp.entries[0].v;
            this._FIREPropertyChange('FailsafeBrakingEnabled', bp);
            break;
          case 192:
            this.data.failsafeCurrentLimit = bp.entries[0].v;
            this._FIREPropertyChange('FailsafeCurrentLimit', bp);
            break;
          case 58:
            this.data.fanMode = bp.entries[0].v;
            this._FIREPropertyChange('FanMode', bp);
            break;
          case 184:
            this.data.inductance = bp.entries[0].v;
            this._FIREPropertyChange('Inductance', bp);
            break;
          case 147:
            break;
          case 194:
            this.data.surgeCurrentLimit = bp.entries[0].v;
            this._FIREPropertyChange('SurgeCurrentLimit', bp);
            break;
          case 44:
            this.data.targetBrakingStrength = bp.entries[0].v;
            this._FIREPropertyChange('TargetBrakingStrength', bp);
            break;
          case 55:
            this.data.targetVelocity = bp.entries[0].v;
            this._FIREPropertyChange('TargetVelocity', bp);
            break;
          case 3:
            {
              this.data.backEMF = bp.entries[0].v;
              if (this._isAttachedDone && this.onBackEMFChange) {
                try {
                  this.onBackEMFChange(this.data.backEMF);
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          case 121:
            {
              this.data.brakingStrength = bp.entries[0].v;
              if (this._isAttachedDone && this.onBrakingStrengthChange) {
                try {
                  this.onBrakingStrengthChange(this.data.brakingStrength);
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          case 16:
            {
              this.data.velocity = bp.entries[0].v;
              if (this._isAttachedDone && this.onVelocityUpdate) {
                try {
                  this.onVelocityUpdate(this.data.velocity);
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          default:
            throw new PhidgetError(exports.ErrorCode.INVALID_PACKET, "Unsupported bridge packet: 0x" + bp.vpkt.toString(16));
        }
      }
      /** @internal */
      _initData() {
        return {
          dataInterval: 1e+300,
          minDataInterval: 4294967295,
          maxDataInterval: 4294967295,
          minDataRate: 1e+300,
          maxDataRate: 1e+300,
          currentLimit: 1e+300,
          surgeCurrentLimit: 1e+300,
          maxSurgeCurrentLimit: 1e+300,
          minSurgeCurrentLimit: 1e+300,
          maxCurrentLimit: 1e+300,
          minCurrentLimit: 1e+300,
          activeCurrentLimit: 1e+300,
          currentRegulatorGain: 1e+300,
          maxCurrentRegulatorGain: 1e+300,
          minCurrentRegulatorGain: 1e+300,
          targetVelocity: 1e+300,
          maxVelocity: 1e+300,
          minVelocity: 1e+300,
          maxAcceleration: 1e+300,
          minAcceleration: 1e+300,
          acceleration: 1e+300,
          targetBrakingStrength: 1e+300,
          maxBrakingStrength: 1e+300,
          minBrakingStrength: 1e+300,
          failsafeCurrentLimit: 1e+300,
          failsafeBrakingEnabled: 2,
          backEMFSensingState: 2,
          backEMF: 1e+300,
          fanMode: 2147483647,
          velocity: 1e+300,
          brakingStrength: 1e+300,
          maxFailsafeTime: 4294967295,
          minFailsafeTime: 4294967295,
          inductance: 1e+300,
          maxInductance: 1e+300,
          minInductance: 1e+300,
          driveMode: 2147483647
        };
      }
      /** @internal */
      _initAfterOpen() {}
      /** @internal */
      async _setDefaults() {}
      /** @internal */
      _hasInitialState() {
        return true;
      }
      /** @internal */
      _fireInitialEvents() {}
      /**
       * The rate at which the controller can change the motor's `velocity`.
       * @throws `PhidgetError`
       */
      get acceleration() {
        return this.getAcceleration();
      }
      /**
       * The minimum value that `acceleration` can be set to.
       * @throws `PhidgetError`
       */
      get minAcceleration() {
        return this.getMinAcceleration();
      }
      /**
       * The maximum value that `acceleration` can be set to.
       * @throws `PhidgetError`
       */
      get maxAcceleration() {
        return this.getMaxAcceleration();
      }
      /**
       * The current limit that the controller is actively following. The `surgeCurrentLimit`, `currentLimit`, and temperature will impact this value.
       * @throws `PhidgetError`
       */
      get activeCurrentLimit() {
        return this.getActiveCurrentLimit();
      }
      /**
       * The most recent `backEMF` value that the controller has reported.
       * @throws `PhidgetError`
       */
      get backEMF() {
        return this.getBackEMF();
      }
      /**
       * When `backEMFSensingState` is enabled, the controller will measure and report the `backEMF`.
       *
       * *   The motor will coast (freewheel) 5% of the time while the back EMF is being measured (800μs every 16ms). Therefore, at a `velocity` of 100%, the motor will only be driven for 95% of the time.
       * @throws `PhidgetError`
       */
      get backEMFSensingState() {
        return this.getBackEMFSensingState();
      }
      /**
       * This setting allows you to choose whether the motor will resist being turned when it is not being driven forward or reverse (`velocity` = 0).
       *
       * *   Setting `brakingEnabled` to FALSE corresponds to free-wheeling. This means:
       *     *   The motor will continue to rotate after the controller is no longer driving the motor (`velocity` = 0), due to its momentum.
       *     *   The motor shaft will provide little resistance to being turned when it is stopped.
       * *   Setting `brakingEnabled` to TRUE will engage electrical braking of the DC motor. This means:
       *     *   The motor will stop more quickly if it is in motion when braking is requested.
       *     *   The motor shaft will resist rotation by outside forces.
       * *   Braking will be added gradually, according to the `acceleration` setting, once the motor controller's `velocity` reaches 0.0
       * *   Braking will be immediately stopped when a new (non-zero) `targetVelocity` is set, and the motor will accelerate to the requested velocity.
       * *   Braking mode is enabled by setting the `velocity` to 0.0
       * @throws `PhidgetError`
       */
      get brakingEnabled() {
        return this.getBrakingEnabled();
      }
      /**
       * The most recent braking strength value that the controller has reported. See `brakingEnabled` for details.
       * @throws `PhidgetError`
       */
      get brakingStrength() {
        return this.getBrakingStrength();
      }
      /**
       * The minimum value that `brakingStrength` can be set to.
       * @throws `PhidgetError`
       */
      get minBrakingStrength() {
        return this.getMinBrakingStrength();
      }
      /**
       * The maximum value that `brakingStrength` can be set to.
       * @throws `PhidgetError`
       */
      get maxBrakingStrength() {
        return this.getMaxBrakingStrength();
      }
      /**
       * The controller will limit the current through the motor to the `currentLimit` value.
       * @throws `PhidgetError`
       */
      get currentLimit() {
        return this.getCurrentLimit();
      }
      /**
       * The minimum value that `currentLimit` can be set to.
       * @throws `PhidgetError`
       */
      get minCurrentLimit() {
        return this.getMinCurrentLimit();
      }
      /**
       * The maximum value that `currentLimit` can be set to.
       * @throws `PhidgetError`
       */
      get maxCurrentLimit() {
        return this.getMaxCurrentLimit();
      }
      /**
       * Depending on power supply voltage and motor coil inductance, current through the motor can change relatively slowly or extremely rapidly. A physically larger DC Motor will typically have a lower inductance, requiring a higher current regulator gain. A higher power supply voltage will result in motor current changing more rapidly, requiring a higher current regulator gain. If the current regulator gain is too small, spikes in current will occur, causing large variations in torque, and possibly damaging the motor controller. If the current regulator gain is too high, the current will jitter, causing the motor to sound 'rough', especially when changing directions.
       *
       * As a rule of thumb, we recommend setting this value as follows:
       *
       * CurrentRegulatorGain = CurrentLimit \* (Voltage / 12)
       * @throws `PhidgetError`
       */
      get currentRegulatorGain() {
        return this.getCurrentRegulatorGain();
      }
      /**
       * The minimum value that `currentRegulatorGain` can be set to.
       * @throws `PhidgetError`
       */
      get minCurrentRegulatorGain() {
        return this.getMinCurrentRegulatorGain();
      }
      /**
       * The maximum value that `currentRegulatorGain` can be set to.
       * @throws `PhidgetError`
       */
      get maxCurrentRegulatorGain() {
        return this.getMaxCurrentRegulatorGain();
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `VelocityUpdate` / `BrakingStrengthChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       *
       * *   Note: `BrakingStrengthChange` events will only fire if a change in braking has occurred.
       * @throws `PhidgetError`
       */
      get dataInterval() {
        return this.getDataInterval();
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get minDataInterval() {
        return this.getMinDataInterval();
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataInterval() {
        return this.getMaxDataInterval();
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       */
      get dataRate() {
        return this.getDataRate();
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get minDataRate() {
        return this.getMinDataRate();
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataRate() {
        return this.getMaxDataRate();
      }
      /**
       * This setting impacts how your motor decelerates and the amount of current that is available to your motor at any given moment.
       *
       *
       * For more information about `driveMode`, visit our [DCMotor API Guide](https://www.phidgets.com/docs/DCMotor_API_Guide#Drive_Mode)
       * @throws `PhidgetError`
       */
      get driveMode() {
        return this.getDriveMode();
      }
      /**
       * This setting allows you to choose whether motor will forcibly stop once it enters a **FAILSAFE** state.
       *
       * *   A setting of FALSE will simply stop applying power to the motor, allowing it to spin down naturally.
       * *   A setting of TRUE will apply braking up to the `failsafeCurrentLimit`, actively stopping the motor
       *
       *
       * For more information about `failsafeBrakingEnabled`, visit our [DCMotor API Guide](https://www.phidgets.com/docs/DCMotor_API_Guide#Failsafe_Braking_Enabled)
       * @throws `PhidgetError`
       */
      get failsafeBrakingEnabled() {
        return this.getFailsafeBrakingEnabled();
      }
      /**
       * When the controller enters a **FAILSAFE** state, the controller will limit the current through the motor to the `failsafeCurrentLimit` value.
       *
       *
       * For more information about `failsafeCurrentLimit`, visit our [DCMotor API Guide](https://www.phidgets.com/docs/DCMotor_API_Guide#Failsafe_Current_Limit)
       * @throws `PhidgetError`
       */
      get failsafeCurrentLimit() {
        return this.getFailsafeCurrentLimit();
      }
      /**
       * The minimum value that `failsafeTime` can be set to when calling `enableFailsafe()`.
       * @throws `PhidgetError`
       */
      get minFailsafeTime() {
        return this.getMinFailsafeTime();
      }
      /**
       * The maximum value that `failsafeTime` can be set to when calling `enableFailsafe()`.
       * @throws `PhidgetError`
       */
      get maxFailsafeTime() {
        return this.getMaxFailsafeTime();
      }
      /**
       * The `fanMode` dictates the operating condition of the fan.
       *
       * *   Choose between on, off, or automatic (based on temperature).
       * *   If the `fanMode` is set to automatic, the fan will turn on when the temperature reaches 70°C and it will remain on until the temperature falls below 55°C.
       * *   If the `fanMode` is off, the controller will still turn on the fan if the temperature reaches 85°C and it will remain on until it falls below 70°C.
       * @throws `PhidgetError`
       */
      get fanMode() {
        return this.getFanMode();
      }
      /**
       * The controller will attempt to measure the inductance of your motor when opened. This value is used to improve control of the motor.
       *
       * *   Set this value during the **Attach Event** to skip motor characterization (including the audible beeps). You can use a previously saved `inductance` value, or information from your motor's datasheet.
       *
       *
       * For more information about `inductance`, visit our [DCMotor API Guide](https://www.phidgets.com/docs/DCMotor_API_Guide#Motor_Inductance)
       * @throws `PhidgetError`
       */
      get inductance() {
        return this.getInductance();
      }
      /**
       * The minimum value that `inductance` can be set to. See `inductance` for details.
       * @throws `PhidgetError`
       */
      get minInductance() {
        return this.getMinInductance();
      }
      /**
       * The maximum value that `inductance` can be set to. See `inductance` for details.
       * @throws `PhidgetError`
       */
      get maxInductance() {
        return this.getMaxInductance();
      }
      /**
       * The `surgeCurrentLimit` allows for increased performance from your motor. The controller will limit the current through your motor to the `surgeCurrentLimit` briefly, then scale current down to the `currentLimit`.
       *
       * *   View `activeCurrentLimit` for information about what current limit the controller is actively following.
       *
       *
       * For more information about `surgeCurrentLimit`, visit our [DCMotor API Guide](https://www.phidgets.com/docs/DCMotor_API_Guide#Surge_Current_Limit)
       * @throws `PhidgetError`
       */
      get surgeCurrentLimit() {
        return this.getSurgeCurrentLimit();
      }
      /**
       * The minimum value that `surgeCurrentLimit` can be set to.
       * @throws `PhidgetError`
       */
      get minSurgeCurrentLimit() {
        return this.getMinSurgeCurrentLimit();
      }
      /**
       * The maximum value that `surgeCurrentLimit` can be set to.
       * @throws `PhidgetError`
       */
      get maxSurgeCurrentLimit() {
        return this.getMaxSurgeCurrentLimit();
      }
      /**
       * This setting allows you to choose how hard the motor will resist being turned when it is not being driven forward or reverse (`velocity` = 0). The `targetBrakingStrength` sets the relative amount of electrical braking to be applied to the DC motor, with `minBrakingStrength` corresponding to no braking (free-wheeling), and `maxBrakingStrength` indicating full braking.
       *
       * *   A low `targetBrakingStrength` value corresponds to free-wheeling. This means:
       *     *   The motor will continue to rotate after the controller is no longer driving the motor (`velocity` = 0), due to its momentum.
       *     *   The motor shaft will provide little resistance to being turned when it is stopped.
       * *   As `targetBrakingStrength` increases, this will engage electrical braking of the DC motor. This means:
       *     *   The motor will stop more quickly if it is in motion when braking is requested.
       *     *   The motor shaft will resist rotation by outside forces.
       * *   Braking will be added gradually, according to the `acceleration` setting, once the motor controller's `velocity` reaches 0.0
       * *   Braking will be immediately stopped when a new (non-zero) `targetVelocity` is set, and the motor will accelerate to the requested velocity.
       * *   Braking mode is enabled by setting the `velocity` to 0.0
       * @throws `PhidgetError`
       */
      get targetBrakingStrength() {
        return this.getTargetBrakingStrength();
      }
      /**
       * The average voltage across the motor is based on the `targetVelocity` value.
       *
       * *   At a constant load, increasing the target velocity will increase the speed of the motor.
       * *   `targetVelocity` is bounded by -`maxVelocity` and +`maxVelocity`, where a sign change (±) is indicative of a direction change.
       * *   Setting `targetVelocity` to `minVelocity` will stop the motor. See `brakingEnabled` for more information on stopping the motor.
       * @throws `PhidgetError`
       */
      get targetVelocity() {
        return this.getTargetVelocity();
      }
      /**
       * The most recent `velocity` value that the controller has reported.
       * @throws `PhidgetError`
       */
      get velocity() {
        return this.getVelocity();
      }
      /**
       * The minimum value that `targetVelocity` can be set to.
       *
       * *   Set the `targetVelocity` to `minVelocity` to stop the motor. See `brakingEnabled` for more information on stopping the motor.
       * *   `targetVelocity` is bounded by -`maxVelocity` and +`maxVelocity`, where a sign change (±) is indicative of a direction change.
       * @throws `PhidgetError`
       */
      get minVelocity() {
        return this.getMinVelocity();
      }
      /**
       * The maximum value that `targetVelocity` can be set to.
       *
       * *   `targetVelocity` is bounded by -`maxVelocity` and +`maxVelocity`, where a sign change (±) is indicative of a direction change.
       * @throws `PhidgetError`
       */
      get maxVelocity() {
        return this.getMaxVelocity();
      }
      /**
       * The rate at which the controller can change the motor's `velocity`.
       * @returns The acceleration value
       * @throws `PhidgetError`
       */
      getAcceleration() {
        this._assertOpen();
        if (this.data.acceleration === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.acceleration;
      }
      /**
       * The rate at which the controller can change the motor's `velocity`.
       * @throws `PhidgetError`
       * @param acceleration - The acceleration value
       */
      async setAcceleration(acceleration) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: acceleration
        });
        await bp.send(this._ch, 40);
      }
      /**
       * The minimum value that `acceleration` can be set to.
       * @returns The acceleration value.
       * @throws `PhidgetError`
       */
      getMinAcceleration() {
        this._assertOpen();
        if (this.data.minAcceleration === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minAcceleration;
      }
      /**
       * The maximum value that `acceleration` can be set to.
       * @returns The acceleration value.
       * @throws `PhidgetError`
       */
      getMaxAcceleration() {
        this._assertOpen();
        if (this.data.maxAcceleration === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxAcceleration;
      }
      /**
       * The current limit that the controller is actively following. The `surgeCurrentLimit`, `currentLimit`, and temperature will impact this value.
       * @returns The active current limit value
       * @throws `PhidgetError`
       */
      getActiveCurrentLimit() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 277:
          case 284:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.activeCurrentLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.activeCurrentLimit;
      }
      /**
       * The most recent `backEMF` value that the controller has reported.
       * @returns The back EMF value
       * @throws `PhidgetError`
       */
      getBackEMF() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 172:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.backEMF === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.backEMF;
      }
      /**
       * When `backEMFSensingState` is enabled, the controller will measure and report the `backEMF`.
       *
       * *   The motor will coast (freewheel) 5% of the time while the back EMF is being measured (800μs every 16ms). Therefore, at a `velocity` of 100%, the motor will only be driven for 95% of the time.
       * @returns The back EMF state
       * @throws `PhidgetError`
       */
      getBackEMFSensingState() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 172:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.backEMFSensingState === 2) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return !!this.data.backEMFSensingState;
      }
      /**
       * When `backEMFSensingState` is enabled, the controller will measure and report the `backEMF`.
       *
       * *   The motor will coast (freewheel) 5% of the time while the back EMF is being measured (800μs every 16ms). Therefore, at a `velocity` of 100%, the motor will only be driven for 95% of the time.
       * @throws `PhidgetError`
       * @param backEMFSensingState - The back EMF state
       */
      async setBackEMFSensingState(backEMFSensingState) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: backEMFSensingState ? 1 : 0
        });
        await bp.send(this._ch, 42);
      }
      /**
       * The most recent braking strength value that the controller has reported. See `brakingEnabled` for details.
       * @returns The braking strength value
       * @throws `PhidgetError`
       */
      getBrakingStrength() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 158:
          case 170:
          case 172:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.brakingStrength === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.brakingStrength;
      }
      /**
       * The minimum value that `brakingStrength` can be set to.
       * @returns The braking strength value
       * @throws `PhidgetError`
       */
      getMinBrakingStrength() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 158:
          case 170:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.minBrakingStrength === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minBrakingStrength;
      }
      /**
       * The maximum value that `brakingStrength` can be set to.
       * @returns The braking strength value
       * @throws `PhidgetError`
       */
      getMaxBrakingStrength() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 158:
          case 170:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.maxBrakingStrength === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxBrakingStrength;
      }
      /**
       * The controller will limit the current through the motor to the `currentLimit` value.
       * @returns The current limit value
       * @throws `PhidgetError`
       */
      getCurrentLimit() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 158:
          case 170:
          case 172:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.currentLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.currentLimit;
      }
      /**
       * The controller will limit the current through the motor to the `currentLimit` value.
       * @throws `PhidgetError`
       * @param currentLimit - The current limit value
       */
      async setCurrentLimit(currentLimit) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: currentLimit
        });
        await bp.send(this._ch, 51);
      }
      /**
       * The minimum value that `currentLimit` can be set to.
       * @returns The current value
       * @throws `PhidgetError`
       */
      getMinCurrentLimit() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 158:
          case 170:
          case 172:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.minCurrentLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minCurrentLimit;
      }
      /**
       * The maximum value that `currentLimit` can be set to.
       * @returns The current value
       * @throws `PhidgetError`
       */
      getMaxCurrentLimit() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 158:
          case 170:
          case 172:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.maxCurrentLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxCurrentLimit;
      }
      /**
       * Depending on power supply voltage and motor coil inductance, current through the motor can change relatively slowly or extremely rapidly. A physically larger DC Motor will typically have a lower inductance, requiring a higher current regulator gain. A higher power supply voltage will result in motor current changing more rapidly, requiring a higher current regulator gain. If the current regulator gain is too small, spikes in current will occur, causing large variations in torque, and possibly damaging the motor controller. If the current regulator gain is too high, the current will jitter, causing the motor to sound 'rough', especially when changing directions.
       *
       * As a rule of thumb, we recommend setting this value as follows:
       *
       * CurrentRegulatorGain = CurrentLimit \* (Voltage / 12)
       * @returns The current regulator gain value
       * @throws `PhidgetError`
       */
      getCurrentRegulatorGain() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 245:
          case 250:
          case 256:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.currentRegulatorGain === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.currentRegulatorGain;
      }
      /**
       * Depending on power supply voltage and motor coil inductance, current through the motor can change relatively slowly or extremely rapidly. A physically larger DC Motor will typically have a lower inductance, requiring a higher current regulator gain. A higher power supply voltage will result in motor current changing more rapidly, requiring a higher current regulator gain. If the current regulator gain is too small, spikes in current will occur, causing large variations in torque, and possibly damaging the motor controller. If the current regulator gain is too high, the current will jitter, causing the motor to sound 'rough', especially when changing directions.
       *
       * As a rule of thumb, we recommend setting this value as follows:
       *
       * CurrentRegulatorGain = CurrentLimit \* (Voltage / 12)
       * @throws `PhidgetError`
       * @param currentRegulatorGain - The current regulator gain value
       */
      async setCurrentRegulatorGain(currentRegulatorGain) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: currentRegulatorGain
        });
        await bp.send(this._ch, 119);
      }
      /**
       * The minimum value that `currentRegulatorGain` can be set to.
       * @returns The current regulator gain value
       * @throws `PhidgetError`
       */
      getMinCurrentRegulatorGain() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 245:
          case 250:
          case 256:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.minCurrentRegulatorGain === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minCurrentRegulatorGain;
      }
      /**
       * The maximum value that `currentRegulatorGain` can be set to.
       * @returns The current regulator gain value
       * @throws `PhidgetError`
       */
      getMaxCurrentRegulatorGain() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 245:
          case 250:
          case 256:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.maxCurrentRegulatorGain === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxCurrentRegulatorGain;
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `VelocityUpdate` / `BrakingStrengthChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       *
       * *   Note: `BrakingStrengthChange` events will only fire if a change in braking has occurred.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getDataInterval() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.dataInterval;
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `VelocityUpdate` / `BrakingStrengthChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       *
       * *   Note: `BrakingStrengthChange` events will only fire if a change in braking has occurred.
       * @throws `PhidgetError`
       * @param dataInterval - The data interval value
       */
      async setDataInterval(dataInterval) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: dataInterval
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMinDataInterval() {
        this._assertOpen();
        if (this.data.minDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataInterval;
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMaxDataInterval() {
        this._assertOpen();
        if (this.data.maxDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @returns The data rate for the channel
       * @throws `PhidgetError`
       */
      getDataRate() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return 1000.0 / this.data.dataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       * @param dataRate - The data rate for the channel
       */
      async setDataRate(dataRate) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: Math.round(1000.0 / dataRate)
        });
        bp.set({
          name: "1",
          type: "g",
          value: 1000.0 / dataRate
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMinDataRate() {
        this._assertOpen();
        if (this.data.minDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataRate;
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMaxDataRate() {
        this._assertOpen();
        if (this.data.maxDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataRate;
      }
      /**
       * This setting impacts how your motor decelerates and the amount of current that is available to your motor at any given moment.
       *
       *
       * For more information about `driveMode`, visit our [DCMotor API Guide](https://www.phidgets.com/docs/DCMotor_API_Guide#Drive_Mode)
       * @returns The drive type selection
       * @throws `PhidgetError`
       */
      getDriveMode() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 277:
          case 284:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.driveMode === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.driveMode;
      }
      /**
       * This setting impacts how your motor decelerates and the amount of current that is available to your motor at any given moment.
       *
       *
       * For more information about `driveMode`, visit our [DCMotor API Guide](https://www.phidgets.com/docs/DCMotor_API_Guide#Drive_Mode)
       * @throws `PhidgetError`
       * @param driveMode - The drive type selection
       */
      async setDriveMode(driveMode) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: driveMode
        });
        await bp.send(this._ch, 186);
      }
      /**
       * Enables the **failsafe** feature for the channel, with the specified **failsafe time**.
       *
       * Enabling the failsafe feature starts a recurring **failsafe timer** for the channel. Once the failsafe is enabled, the timer must be reset within the specified time or the channel will enter a **failsafe state**. For DC Motor channels, this will disengage the motor. The failsafe timer can be reset by using any API call **_except_** for 'get' API calls.
       *
       * For more information about failsafe, visit our [Failsafe Guide](https://www.phidgets.com/docs/Failsafe_Guide).
       * @throws `PhidgetError`
       * @param failsafeTime - Failsafe timeout in milliseconds
       */
      async enableFailsafe(failsafeTime) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: failsafeTime
        });
        await bp.send(this._ch, 146);
      }
      /**
       * This setting allows you to choose whether motor will forcibly stop once it enters a **FAILSAFE** state.
       *
       * *   A setting of FALSE will simply stop applying power to the motor, allowing it to spin down naturally.
       * *   A setting of TRUE will apply braking up to the `failsafeCurrentLimit`, actively stopping the motor
       *
       *
       * For more information about `failsafeBrakingEnabled`, visit our [DCMotor API Guide](https://www.phidgets.com/docs/DCMotor_API_Guide#Failsafe_Braking_Enabled)
       * @returns Enables failsafe braking
       * @throws `PhidgetError`
       */
      getFailsafeBrakingEnabled() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 277:
          case 284:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.failsafeBrakingEnabled === 2) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return !!this.data.failsafeBrakingEnabled;
      }
      /**
       * This setting allows you to choose whether motor will forcibly stop once it enters a **FAILSAFE** state.
       *
       * *   A setting of FALSE will simply stop applying power to the motor, allowing it to spin down naturally.
       * *   A setting of TRUE will apply braking up to the `failsafeCurrentLimit`, actively stopping the motor
       *
       *
       * For more information about `failsafeBrakingEnabled`, visit our [DCMotor API Guide](https://www.phidgets.com/docs/DCMotor_API_Guide#Failsafe_Braking_Enabled)
       * @throws `PhidgetError`
       * @param failsafeBrakingEnabled - Enables failsafe braking
       */
      async setFailsafeBrakingEnabled(failsafeBrakingEnabled) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: failsafeBrakingEnabled ? 1 : 0
        });
        await bp.send(this._ch, 193);
      }
      /**
       * When the controller enters a **FAILSAFE** state, the controller will limit the current through the motor to the `failsafeCurrentLimit` value.
       *
       *
       * For more information about `failsafeCurrentLimit`, visit our [DCMotor API Guide](https://www.phidgets.com/docs/DCMotor_API_Guide#Failsafe_Current_Limit)
       * @returns The failsafe current limit value
       * @throws `PhidgetError`
       */
      getFailsafeCurrentLimit() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 277:
          case 284:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.failsafeCurrentLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.failsafeCurrentLimit;
      }
      /**
       * When the controller enters a **FAILSAFE** state, the controller will limit the current through the motor to the `failsafeCurrentLimit` value.
       *
       *
       * For more information about `failsafeCurrentLimit`, visit our [DCMotor API Guide](https://www.phidgets.com/docs/DCMotor_API_Guide#Failsafe_Current_Limit)
       * @throws `PhidgetError`
       * @param failsafeCurrentLimit - The failsafe current limit value
       */
      async setFailsafeCurrentLimit(failsafeCurrentLimit) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: failsafeCurrentLimit
        });
        await bp.send(this._ch, 192);
      }
      /**
       * The minimum value that `failsafeTime` can be set to when calling `enableFailsafe()`.
       * @returns The failsafe time
       * @throws `PhidgetError`
       */
      getMinFailsafeTime() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 256:
          case 277:
          case 284:
          case 265:
          case 271:
          case 275:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.minFailsafeTime === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minFailsafeTime;
      }
      /**
       * The maximum value that `failsafeTime` can be set to when calling `enableFailsafe()`.
       * @returns The failsafe time
       * @throws `PhidgetError`
       */
      getMaxFailsafeTime() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 256:
          case 277:
          case 284:
          case 265:
          case 271:
          case 275:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.maxFailsafeTime === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxFailsafeTime;
      }
      /**
       * The `fanMode` dictates the operating condition of the fan.
       *
       * *   Choose between on, off, or automatic (based on temperature).
       * *   If the `fanMode` is set to automatic, the fan will turn on when the temperature reaches 70°C and it will remain on until the temperature falls below 55°C.
       * *   If the `fanMode` is off, the controller will still turn on the fan if the temperature reaches 85°C and it will remain on until it falls below 70°C.
       * @returns The fan mode
       * @throws `PhidgetError`
       */
      getFanMode() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 245:
          case 250:
          case 256:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.fanMode === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.fanMode;
      }
      /**
       * The `fanMode` dictates the operating condition of the fan.
       *
       * *   Choose between on, off, or automatic (based on temperature).
       * *   If the `fanMode` is set to automatic, the fan will turn on when the temperature reaches 70°C and it will remain on until the temperature falls below 55°C.
       * *   If the `fanMode` is off, the controller will still turn on the fan if the temperature reaches 85°C and it will remain on until it falls below 70°C.
       * @throws `PhidgetError`
       * @param fanMode - The fan mode
       */
      async setFanMode(fanMode) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: fanMode
        });
        await bp.send(this._ch, 58);
      }
      /**
       * The controller will attempt to measure the inductance of your motor when opened. This value is used to improve control of the motor.
       *
       * *   Set this value during the **Attach Event** to skip motor characterization (including the audible beeps). You can use a previously saved `inductance` value, or information from your motor's datasheet.
       *
       *
       * For more information about `inductance`, visit our [DCMotor API Guide](https://www.phidgets.com/docs/DCMotor_API_Guide#Motor_Inductance)
       * @returns The inductance of your motor
       * @throws `PhidgetError`
       */
      getInductance() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 277:
          case 284:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.inductance === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.inductance;
      }
      /**
       * The controller will attempt to measure the inductance of your motor when opened. This value is used to improve control of the motor.
       *
       * *   Set this value during the **Attach Event** to skip motor characterization (including the audible beeps). You can use a previously saved `inductance` value, or information from your motor's datasheet.
       *
       *
       * For more information about `inductance`, visit our [DCMotor API Guide](https://www.phidgets.com/docs/DCMotor_API_Guide#Motor_Inductance)
       * @throws `PhidgetError`
       * @param inductance - The inductance of your motor
       */
      async setInductance(inductance) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: inductance
        });
        await bp.send(this._ch, 184);
      }
      /**
       * The minimum value that `inductance` can be set to. See `inductance` for details.
       * @returns The motor inductance value
       * @throws `PhidgetError`
       */
      getMinInductance() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 277:
          case 284:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.minInductance === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minInductance;
      }
      /**
       * The maximum value that `inductance` can be set to. See `inductance` for details.
       * @returns The motor inductance value
       * @throws `PhidgetError`
       */
      getMaxInductance() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 277:
          case 284:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.maxInductance === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxInductance;
      }
      /**
       * Resets the failsafe timer, if one has been set. See `enableFailsafe()` for details.
       *
       * This function will fail if no failsafe timer has been set for the channel.
       * @throws `PhidgetError`
       */
      async resetFailsafe() {
        this._assertOpen();
        const bp = new BridgePacket();
        await bp.send(this._ch, 147);
      }
      /**
       * The `surgeCurrentLimit` allows for increased performance from your motor. The controller will limit the current through your motor to the `surgeCurrentLimit` briefly, then scale current down to the `currentLimit`.
       *
       * *   View `activeCurrentLimit` for information about what current limit the controller is actively following.
       *
       *
       * For more information about `surgeCurrentLimit`, visit our [DCMotor API Guide](https://www.phidgets.com/docs/DCMotor_API_Guide#Surge_Current_Limit)
       * @returns The surge current limit value
       * @throws `PhidgetError`
       */
      getSurgeCurrentLimit() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 277:
          case 284:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.surgeCurrentLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.surgeCurrentLimit;
      }
      /**
       * The `surgeCurrentLimit` allows for increased performance from your motor. The controller will limit the current through your motor to the `surgeCurrentLimit` briefly, then scale current down to the `currentLimit`.
       *
       * *   View `activeCurrentLimit` for information about what current limit the controller is actively following.
       *
       *
       * For more information about `surgeCurrentLimit`, visit our [DCMotor API Guide](https://www.phidgets.com/docs/DCMotor_API_Guide#Surge_Current_Limit)
       * @throws `PhidgetError`
       * @param surgeCurrentLimit - The surge current limit value
       */
      async setSurgeCurrentLimit(surgeCurrentLimit) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: surgeCurrentLimit
        });
        await bp.send(this._ch, 194);
      }
      /**
       * The minimum value that `surgeCurrentLimit` can be set to.
       * @returns The surge current value
       * @throws `PhidgetError`
       */
      getMinSurgeCurrentLimit() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 277:
          case 284:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.minSurgeCurrentLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minSurgeCurrentLimit;
      }
      /**
       * The maximum value that `surgeCurrentLimit` can be set to.
       * @returns The surge current value
       * @throws `PhidgetError`
       */
      getMaxSurgeCurrentLimit() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 277:
          case 284:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.maxSurgeCurrentLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxSurgeCurrentLimit;
      }
      /**
       * This setting allows you to choose how hard the motor will resist being turned when it is not being driven forward or reverse (`velocity` = 0). The `targetBrakingStrength` sets the relative amount of electrical braking to be applied to the DC motor, with `minBrakingStrength` corresponding to no braking (free-wheeling), and `maxBrakingStrength` indicating full braking.
       *
       * *   A low `targetBrakingStrength` value corresponds to free-wheeling. This means:
       *     *   The motor will continue to rotate after the controller is no longer driving the motor (`velocity` = 0), due to its momentum.
       *     *   The motor shaft will provide little resistance to being turned when it is stopped.
       * *   As `targetBrakingStrength` increases, this will engage electrical braking of the DC motor. This means:
       *     *   The motor will stop more quickly if it is in motion when braking is requested.
       *     *   The motor shaft will resist rotation by outside forces.
       * *   Braking will be added gradually, according to the `acceleration` setting, once the motor controller's `velocity` reaches 0.0
       * *   Braking will be immediately stopped when a new (non-zero) `targetVelocity` is set, and the motor will accelerate to the requested velocity.
       * *   Braking mode is enabled by setting the `velocity` to 0.0
       * @returns The braking strength value
       * @throws `PhidgetError`
       */
      getTargetBrakingStrength() {
        this._assertOpen();
        if (this.data.targetBrakingStrength === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.targetBrakingStrength;
      }
      /**
       * This setting allows you to choose how hard the motor will resist being turned when it is not being driven forward or reverse (`velocity` = 0). The `targetBrakingStrength` sets the relative amount of electrical braking to be applied to the DC motor, with `minBrakingStrength` corresponding to no braking (free-wheeling), and `maxBrakingStrength` indicating full braking.
       *
       * *   A low `targetBrakingStrength` value corresponds to free-wheeling. This means:
       *     *   The motor will continue to rotate after the controller is no longer driving the motor (`velocity` = 0), due to its momentum.
       *     *   The motor shaft will provide little resistance to being turned when it is stopped.
       * *   As `targetBrakingStrength` increases, this will engage electrical braking of the DC motor. This means:
       *     *   The motor will stop more quickly if it is in motion when braking is requested.
       *     *   The motor shaft will resist rotation by outside forces.
       * *   Braking will be added gradually, according to the `acceleration` setting, once the motor controller's `velocity` reaches 0.0
       * *   Braking will be immediately stopped when a new (non-zero) `targetVelocity` is set, and the motor will accelerate to the requested velocity.
       * *   Braking mode is enabled by setting the `velocity` to 0.0
       * @throws `PhidgetError`
       * @param targetBrakingStrength - The braking strength value
       */
      async setTargetBrakingStrength(targetBrakingStrength) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: targetBrakingStrength
        });
        await bp.send(this._ch, 44);
      }
      /**
       * The average voltage across the motor is based on the `targetVelocity` value.
       *
       * *   At a constant load, increasing the target velocity will increase the speed of the motor.
       * *   `targetVelocity` is bounded by -`maxVelocity` and +`maxVelocity`, where a sign change (±) is indicative of a direction change.
       * *   Setting `targetVelocity` to `minVelocity` will stop the motor. See `brakingEnabled` for more information on stopping the motor.
       * @returns The velocity value
       * @throws `PhidgetError`
       */
      getTargetVelocity() {
        this._assertOpen();
        if (this.data.targetVelocity === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.targetVelocity;
      }
      /**
       * The average voltage across the motor is based on the `targetVelocity` value.
       *
       * *   At a constant load, increasing the target velocity will increase the speed of the motor.
       * *   `targetVelocity` is bounded by -`maxVelocity` and +`maxVelocity`, where a sign change (±) is indicative of a direction change.
       * *   Setting `targetVelocity` to `minVelocity` will stop the motor. See `brakingEnabled` for more information on stopping the motor.
       * @throws `PhidgetError`
       * @param targetVelocity - The velocity value
       */
      async setTargetVelocity(targetVelocity) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: targetVelocity
        });
        await bp.send(this._ch, 55);
      }
      /**
       * The most recent `velocity` value that the controller has reported.
       * @returns The velocity value
       * @throws `PhidgetError`
       */
      getVelocity() {
        this._assertOpen();
        if (this.data.velocity === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.velocity;
      }
      /**
       * The minimum value that `targetVelocity` can be set to.
       *
       * *   Set the `targetVelocity` to `minVelocity` to stop the motor. See `brakingEnabled` for more information on stopping the motor.
       * *   `targetVelocity` is bounded by -`maxVelocity` and +`maxVelocity`, where a sign change (±) is indicative of a direction change.
       * @returns The velocity value
       * @throws `PhidgetError`
       */
      getMinVelocity() {
        this._assertOpen();
        if (this.data.minVelocity === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minVelocity;
      }
      /**
       * The maximum value that `targetVelocity` can be set to.
       *
       * *   `targetVelocity` is bounded by -`maxVelocity` and +`maxVelocity`, where a sign change (±) is indicative of a direction change.
       * @returns The velocity value
       * @throws `PhidgetError`
       */
      getMaxVelocity() {
        this._assertOpen();
        if (this.data.maxVelocity === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxVelocity;
      }
    }

    /** @public */
    class DCMotor extends DCMotorBase {
      getBrakingEnabled() {
        this._assertOpen();
        if (this.data.targetBrakingStrength === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.targetBrakingStrength == 0 ? false : true;
      }
      async setBrakingEnabled(brakingEnabled) {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 158:
          case 170:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: brakingEnabled ? 1 : 0
        });
        await bp.send(this._ch, 44);
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 10:
            if (bp.entryCount > 1) this.data.dataInterval = bp.getNumber(1);else this.data.dataInterval = bp.getNumber(0);
            this._FIREPropertyChange('DataInterval');
            this._FIREPropertyChange('DataRate');
            break;
          case 196:
            this.data.currentLimit = bp.getNumber(0);
            this._FIREPropertyChange('CurrentLimit');
            break;
          case 185:
            this.data.inductance = bp.getNumber(0);
            this._FIREPropertyChange('Inductance');
            break;
          case 195:
            this.data.surgeCurrentLimit = bp.getNumber(0);
            this._FIREPropertyChange('SurgeCurrentLimit');
            break;
          case 197:
            {
              const tmpDbl = bp.getNumber(0);
              if (this.data.activeCurrentLimit !== tmpDbl) {
                this.data.activeCurrentLimit = tmpDbl;
                this._FIREPropertyChange('ActiveCurrentLimit');
              }
              break;
            }
          default:
            super._bridgeInput(bp);
            break;
        }
      }
      /** @internal */
      async _setDefaults() {
        try {
          await super._setDefaults();
        } catch (err) {
          if (err instanceof PhidgetError) {
            switch (err.errorCode) {
              case exports.ErrorCode.FAILSAFE:
                err.message = "External stop procedure initiated.";
                break;
              case exports.ErrorCode.BAD_POWER:
                err.message = "Your power supply voltage is too high for the motor controller to begin operation.";
                break;
              case exports.ErrorCode.POWER_CYCLE:
                err.message = "An overvoltage fault has triggered. Power your device off and on to resume operation. We recommend a PowerGuard Phidget to prevent this in future.";
                break;
              case exports.ErrorCode.BADCURRENT:
                err.message = "The current sensor is seeing an unacceptable offset in its readings. Move the controller away from magnetic fields and try again.";
                break;
            }
          }
          throw err;
        }
      }
    }

    /**
     * Dictionaries are useful for passing information between multiple programs using Phidgets. A common example would be to have one program controlling your application that receives commands sent via a Phidget dictionary from a web interface, as outlined in many of our [articles](https://www.phidgets.com/?view=articles).
     *
     * Keys can be thought of as being similar to variable names, with their values as their associated value. Phidget dictionaries contain groups of related key-value pairs, and are stored on a central [Phigdet Network Server](https://www.phidgets.com/docs/Phidget_Network_Server). Dictionaries, and the key-value pairs within may be accessed from programs that have access to the [Phigdet Network Server](https://www.phidgets.com/docs/Phidget_Network_Server).
     *
     * The Dictionary API supports connecting to a dictionary on the server, managing key-value pairs, and monitoring changes made to the dictionary.
     *
     * More information on Phidget Dictionaries can be found on the [Phidget Dictionary](https://www.phidgets.com/docs/Phidget_Dictionary) support page.
     * @public
     */
    class DictionaryBase extends PhidgetChannel {
      /** @internal */
      data;
      onAdd = null;
      /** @internal */
      _gotAddErrorEvent;
      onUpdate = null;
      /** @internal */
      _gotUpdateErrorEvent;
      onRemove = null;
      /** @internal */
      _gotRemoveErrorEvent;
      constructor(ch) {
        super(ch);
        this._class = exports.ChannelClass.DICTIONARY;
        this.name = "Dictionary";
        this.data = this._initData();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 123:
            break;
          case 131:
            break;
          case 129:
            break;
          case 127:
            break;
          case 132:
            break;
          case 130:
            break;
          case 125:
            break;
          case 124:
            {
              if (this._isAttachedDone && this.onAdd) {
                try {
                  this.onAdd(bp.entries[0].v, bp.entries[1].v);
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          case 128:
            {
              if (this._isAttachedDone && this.onRemove) {
                try {
                  this.onRemove(bp.entries[0].v);
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          case 126:
            {
              if (this._isAttachedDone && this.onUpdate) {
                try {
                  this.onUpdate(bp.entries[0].v, bp.entries[1].v);
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          default:
            throw new PhidgetError(exports.ErrorCode.INVALID_PACKET, "Unsupported bridge packet: 0x" + bp.vpkt.toString(16));
        }
      }
      /** @internal */
      _initData() {
        return {};
      }
      /** @internal */
      _initAfterOpen() {}
      /** @internal */
      async _setDefaults() {}
      /** @internal */
      _hasInitialState() {
        return true;
      }
      /** @internal */
      _fireInitialEvents() {}
      /**
       * Adds a new key value pair to the dictionary. It is an error if the key already exits.
       * @throws `PhidgetError`
       * @param key - The key to add
       * @param value - The value to add
       */
      async add(key, value) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "s",
          value: key
        });
        bp.set({
          name: "1",
          type: "s",
          value: value
        });
        await bp.send(this._ch, 123);
      }
      /**
       * Removes every key from the dictionary
       * @throws `PhidgetError`
       */
      async removeAll() {
        this._assertOpen();
        const bp = new BridgePacket();
        await bp.send(this._ch, 131);
      }
      /**
       * Removes the key from the dictionary
       * @throws `PhidgetError`
       * @param key - The key to remove
       */
      async remove(key) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "s",
          value: key
        });
        await bp.send(this._ch, 127);
      }
      /**
       * Sets the value of a key, or creates the key value pair if the key does not already exist.
       * @throws `PhidgetError`
       * @param key - The key to set
       * @param value - The value to set
       */
      async set(key, value) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "s",
          value: key
        });
        bp.set({
          name: "1",
          type: "s",
          value: value
        });
        await bp.send(this._ch, 130);
      }
      /**
       * Updates a key value pair in the dictionary. It is an error if the key does not exist.
       * @throws `PhidgetError`
       * @param key - The key to update
       * @param value - The value to set
       */
      async update(key, value) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "s",
          value: key
        });
        bp.set({
          name: "1",
          type: "s",
          value: value
        });
        await bp.send(this._ch, 125);
      }
    }

    /** @public */
    class Dictionary extends DictionaryBase {
      async get(key, def) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "s",
          value: key
        });
        try {
          const val = await bp.send(this._ch, 129);
          return val;
        } catch (err) {
          if (def !== undefined) return def;
          if (err instanceof PhidgetError && err.errorCode === exports.ErrorCode.NO_SUCH_ENTITY) return null;
          throw err;
        }
      }
      async scan(key) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "s",
          value: key ?? ''
        });
        const list = await bp.send(this._ch, 132);
        if (list.length == 0) return [];
        return list.trim().split('\n');
      }
    }

    /**
     * The Digital Input class is used to monitor the state of Phidget digital inputs. Use digital inputs to monitor the state of buttons, switches, or switch-to-ground sensors.
     * @public
     */
    class DigitalInputBase extends PhidgetChannel {
      /** @internal */
      data;
      onStateChange = null;
      /** @internal */
      _gotStateChangeErrorEvent;
      constructor(ch) {
        super(ch);
        this._class = exports.ChannelClass.DIGITAL_INPUT;
        this.name = "DigitalInput";
        this.data = this._initData();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 168:
            this.data.dataAdapterVoltage = bp.entries[0].v;
            this._FIREPropertyChange('DataAdapterVoltage', bp);
            break;
          case 64:
            this.data.inputMode = bp.entries[0].v;
            this._FIREPropertyChange('InputMode', bp);
            break;
          case 74:
            this.data.powerSupply = bp.entries[0].v;
            this._FIREPropertyChange('PowerSupply', bp);
            break;
          case 90:
            {
              this.data.state = bp.entries[0].v;
              if (this._isAttachedDone && this.onStateChange) {
                try {
                  this.onStateChange(!!this.data.state);
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          default:
            throw new PhidgetError(exports.ErrorCode.INVALID_PACKET, "Unsupported bridge packet: 0x" + bp.vpkt.toString(16));
        }
      }
      /** @internal */
      _initData() {
        return {
          state: 2,
          powerSupply: 2147483647,
          inputMode: 2147483647,
          dataAdapterVoltage: 2147483647
        };
      }
      /** @internal */
      _initAfterOpen() {}
      /** @internal */
      async _setDefaults() {}
      /** @internal */
      _hasInitialState() {
        return true;
      }
      /** @internal */
      _fireInitialEvents() {}
      /**
       * The voltage used to communicate with and power the external device.
       * @throws `PhidgetError`
       */
      get dataAdapterVoltage() {
        return this.getDataAdapterVoltage();
      }
      /**
       * The input polarity mode for your channel.
       *
       * *   See your device's User Guide for more information about what value to chooose for the `InputMode`
       * @throws `PhidgetError`
       */
      get inputMode() {
        return this.getInputMode();
      }
      /**
       * Choose the power supply voltage.
       *
       * *   Set this to the voltage specified in the attached sensor's data sheet to power it.
       * *   Set to `phidget22.PowerSupply.OFF` to turn off the supply to save power.
       * @throws `PhidgetError`
       */
      get powerSupply() {
        return this.getPowerSupply();
      }
      /**
       * The most recent state value that the channel has reported.
       * @throws `PhidgetError`
       */
      get state() {
        return this.getState();
      }
      /**
       * The voltage used to communicate with and power the external device.
       * @returns The voltage value
       * @throws `PhidgetError`
       */
      getDataAdapterVoltage() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 202:
          case 205:
          case 208:
          case 211:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.dataAdapterVoltage === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.dataAdapterVoltage;
      }
      /**
       * The voltage used to communicate with and power the external device.
       * @throws `PhidgetError`
       * @param dataAdapterVoltage - The voltage value
       */
      async setDataAdapterVoltage(dataAdapterVoltage) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: dataAdapterVoltage
        });
        await bp.send(this._ch, 168);
      }
      /**
       * The input polarity mode for your channel.
       *
       * *   See your device's User Guide for more information about what value to chooose for the `InputMode`
       * @returns The input mode value
       * @throws `PhidgetError`
       */
      getInputMode() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 202:
          case 205:
          case 234:
          case 238:
          case 242:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.inputMode === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.inputMode;
      }
      /**
       * The input polarity mode for your channel.
       *
       * *   See your device's User Guide for more information about what value to chooose for the `InputMode`
       * @throws `PhidgetError`
       * @param inputMode - The input mode value
       */
      async setInputMode(inputMode) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: inputMode
        });
        await bp.send(this._ch, 64);
      }
      /**
       * Choose the power supply voltage.
       *
       * *   Set this to the voltage specified in the attached sensor's data sheet to power it.
       * *   Set to `phidget22.PowerSupply.OFF` to turn off the supply to save power.
       * @returns The power supply value
       * @throws `PhidgetError`
       */
      getPowerSupply() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 234:
          case 238:
          case 242:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.powerSupply === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.powerSupply;
      }
      /**
       * Choose the power supply voltage.
       *
       * *   Set this to the voltage specified in the attached sensor's data sheet to power it.
       * *   Set to `phidget22.PowerSupply.OFF` to turn off the supply to save power.
       * @throws `PhidgetError`
       * @param powerSupply - The power supply value
       */
      async setPowerSupply(powerSupply) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: powerSupply
        });
        await bp.send(this._ch, 74);
      }
      /**
       * The most recent state value that the channel has reported.
       * @returns The state value
       * @throws `PhidgetError`
       */
      getState() {
        this._assertOpen();
        if (this.data.state === 2) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return !!this.data.state;
      }
    }

    /** @public */
    class DigitalInput extends DigitalInputBase {
      /** @internal */
      _errorHandler(code) {
        switch (code) {
          default:
            this.data.state = 2;
            break;
        }
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 202:
            if (this.data.dataAdapterVoltage !== bp.entries[0].v) {
              this.data.dataAdapterVoltage = bp.entries[0].v;
              this._FIREPropertyChange('DataAdapterVoltage', bp);
            }
            break;
          case 181:
            this.data.powerSupply = bp.entries[0].v;
            this._FIREPropertyChange('PowerSupply', bp);
            break;
          case 182:
            this.data.inputMode = bp.entries[0].v;
            this._FIREPropertyChange('InputMode', bp);
            break;
          default:
            super._bridgeInput(bp);
            break;
        }
      }
    }

    /**
     * The Digital Output class is used to control digital logic outputs and LED outputs on Phidgets boards.
     * @public
     */
    class DigitalOutputBase extends PhidgetChannel {
      /** @internal */
      data;
      constructor(ch) {
        super(ch);
        this._class = exports.ChannelClass.DIGITAL_OUTPUT;
        this.name = "DigitalOutput";
        this.data = this._initData();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 168:
            this.data.dataAdapterVoltage = bp.entries[0].v;
            this._FIREPropertyChange('DataAdapterVoltage', bp);
            break;
          case 55:
            this.data.dutyCycle = bp.entries[0].v;
            this._FIREPropertyChange('DutyCycle', bp);
            break;
          case 146:
            break;
          case 156:
            this.data.frequency = bp.entries[0].v;
            this._FIREPropertyChange('Frequency', bp);
            break;
          case 67:
            this.data.LEDCurrentLimit = bp.entries[0].v;
            this._FIREPropertyChange('LEDCurrentLimit', bp);
            break;
          case 68:
            this.data.LEDForwardVoltage = bp.entries[0].v;
            this._FIREPropertyChange('LEDForwardVoltage', bp);
            break;
          case 147:
            break;
          case 82:
            this.data.state = bp.entries[0].v;
            this._FIREPropertyChange('State', bp);
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.INVALID_PACKET, "Unsupported bridge packet: 0x" + bp.vpkt.toString(16));
        }
      }
      /** @internal */
      _initData() {
        return {
          dutyCycle: 1e+300,
          maxDutyCycle: 1e+300,
          minDutyCycle: 1e+300,
          LEDCurrentLimit: 1e+300,
          minLEDCurrentLimit: 1e+300,
          maxLEDCurrentLimit: 1e+300,
          LEDForwardVoltage: 2147483647,
          state: 2,
          maxFailsafeTime: 4294967295,
          minFailsafeTime: 4294967295,
          frequency: 1e+300,
          maxFrequency: 1e+300,
          minFrequency: 1e+300,
          dataAdapterVoltage: 2147483647
        };
      }
      /** @internal */
      _initAfterOpen() {}
      /** @internal */
      async _setDefaults() {}
      /** @internal */
      _hasInitialState() {
        return true;
      }
      /** @internal */
      _fireInitialEvents() {}
      /**
       * The voltage used to communicate with and power the external device.
       * @throws `PhidgetError`
       */
      get dataAdapterVoltage() {
        return this.getDataAdapterVoltage();
      }
      /**
       * The `dutyCycle` represents the fraction of time the output is on (high).
       *
       * *   A `dutyCycle` of 1.0 translates to a high output, a `dutyCycle` of 0 translates to a low output.
       * *   A `dutyCycle` of 0.5 translates to an output that is high half the time, which results in an average output voltage of (output voltage x 0.5)
       * *   You can use the `dutyCycle` to create a dimming effect on LEDs.
       * @throws `PhidgetError`
       */
      get dutyCycle() {
        return this.getDutyCycle();
      }
      /**
       * The minimum value that `dutyCycle` can be set to.
       * @throws `PhidgetError`
       */
      get minDutyCycle() {
        return this.getMinDutyCycle();
      }
      /**
       * The maximum value that `dutyCycle` can be set to.
       * @throws `PhidgetError`
       */
      get maxDutyCycle() {
        return this.getMaxDutyCycle();
      }
      /**
       * The minimum value that `failsafeTime` can be set to when calling `enableFailsafe()`.
       * @throws `PhidgetError`
       */
      get minFailsafeTime() {
        return this.getMinFailsafeTime();
      }
      /**
       * The maximum value that `failsafeTime` can be set to when calling `enableFailsafe()`.
       * @throws `PhidgetError`
       */
      get maxFailsafeTime() {
        return this.getMaxFailsafeTime();
      }
      /**
       * The `frequency` parameter sets the PWM frequency for all frequency-settable PWM outputs on the board.
       * @throws `PhidgetError`
       */
      get frequency() {
        return this.getFrequency();
      }
      /**
       * The minimum value that `frequency` can be set to.
       * @throws `PhidgetError`
       */
      get minFrequency() {
        return this.getMinFrequency();
      }
      /**
       * The maximum value that `frequency` can be set to.
       * @throws `PhidgetError`
       */
      get maxFrequency() {
        return this.getMaxFrequency();
      }
      /**
       * The `LEDCurrentLimit` is the maximum amount of current that the controller will provide to the output.
       *
       * *   Reference the data sheet of the LED you are using before setting this value.
       * @throws `PhidgetError`
       */
      get LEDCurrentLimit() {
        return this.getLEDCurrentLimit();
      }
      /**
       * The minimum value that `LEDCurrentLimit` can be set to.
       * @throws `PhidgetError`
       */
      get minLEDCurrentLimit() {
        return this.getMinLEDCurrentLimit();
      }
      /**
       * The maximum value that `LEDCurrentLimit` can be set to.
       * @throws `PhidgetError`
       */
      get maxLEDCurrentLimit() {
        return this.getMaxLEDCurrentLimit();
      }
      /**
       * The `LEDForwardVoltage` is the voltage that will be available to your LED.
       *
       * *   Reference the data sheet of the LED you are using before setting this value. Choose the `LEDForwardVoltage` that is closest to the forward voltage specified in the data sheet.
       * *   This forward voltage is shared for all channels on this device. Setting the LEDForwardVoltage on any channel will set the LEDForwardVoltage for all channels on the device.
       * @throws `PhidgetError`
       */
      get LEDForwardVoltage() {
        return this.getLEDForwardVoltage();
      }
      /**
       * The `state` will indicate whether the output is high (TRUE) or low (FALSE).
       *
       * *   If a `dutyCycle` has been set, the state will return as TRUE if the DutyCycle is above 0.5, or FALSE otherwise.
       * @throws `PhidgetError`
       */
      get state() {
        return this.getState();
      }
      /**
       * The voltage used to communicate with and power the external device.
       * @returns The voltage value
       * @throws `PhidgetError`
       */
      getDataAdapterVoltage() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 203:
          case 206:
          case 209:
          case 212:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.dataAdapterVoltage === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.dataAdapterVoltage;
      }
      /**
       * The voltage used to communicate with and power the external device.
       * @throws `PhidgetError`
       * @param dataAdapterVoltage - The voltage value
       */
      async setDataAdapterVoltage(dataAdapterVoltage) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: dataAdapterVoltage
        });
        await bp.send(this._ch, 168);
      }
      /**
       * The `dutyCycle` represents the fraction of time the output is on (high).
       *
       * *   A `dutyCycle` of 1.0 translates to a high output, a `dutyCycle` of 0 translates to a low output.
       * *   A `dutyCycle` of 0.5 translates to an output that is high half the time, which results in an average output voltage of (output voltage x 0.5)
       * *   You can use the `dutyCycle` to create a dimming effect on LEDs.
       * @returns The duty cycle value
       * @throws `PhidgetError`
       */
      getDutyCycle() {
        this._assertOpen();
        if (this.data.dutyCycle === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.dutyCycle;
      }
      /**
       * The `dutyCycle` represents the fraction of time the output is on (high).
       *
       * *   A `dutyCycle` of 1.0 translates to a high output, a `dutyCycle` of 0 translates to a low output.
       * *   A `dutyCycle` of 0.5 translates to an output that is high half the time, which results in an average output voltage of (output voltage x 0.5)
       * *   You can use the `dutyCycle` to create a dimming effect on LEDs.
       * @throws `PhidgetError`
       * @param dutyCycle - The duty cycle value
       */
      async setDutyCycle(dutyCycle) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: dutyCycle
        });
        await bp.send(this._ch, 55);
      }
      /**
       * The minimum value that `dutyCycle` can be set to.
       * @returns The duty cycle value
       * @throws `PhidgetError`
       */
      getMinDutyCycle() {
        this._assertOpen();
        if (this.data.minDutyCycle === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDutyCycle;
      }
      /**
       * The maximum value that `dutyCycle` can be set to.
       * @returns The duty cycle value
       * @throws `PhidgetError`
       */
      getMaxDutyCycle() {
        this._assertOpen();
        if (this.data.maxDutyCycle === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDutyCycle;
      }
      /**
       * Enables the **failsafe** feature for the channel, with the specified **failsafe time**.
       *
       * Enabling the failsafe feature starts a recurring **failsafe timer** for the channel. Once the failsafe is enabled, the timer must be reset within the specified time or the channel will enter a **failsafe state**. For Digital Output channels, this will set the output State to FALSE. The failsafe timer can be reset by using any of the following API calls:
       *
       * *   `setDutyCycle()`
       * *   `setState()`
       * *   `setFrequency()`
       * *   `resetFailsafe()`
       *
       * For more information about failsafe, visit our [Failsafe Guide](https://www.phidgets.com/docs/Failsafe_Guide).
       * @throws `PhidgetError`
       * @param failsafeTime - Failsafe timeout in milliseconds
       */
      async enableFailsafe(failsafeTime) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: failsafeTime
        });
        await bp.send(this._ch, 146);
      }
      /**
       * The minimum value that `failsafeTime` can be set to when calling `enableFailsafe()`.
       * @returns The failsafe time
       * @throws `PhidgetError`
       */
      getMinFailsafeTime() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 40:
          case 41:
          case 45:
          case 46:
          case 472:
          case 401:
          case 402:
          case 409:
          case 411:
          case 412:
          case 414:
          case 415:
          case 416:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.minFailsafeTime === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minFailsafeTime;
      }
      /**
       * The maximum value that `failsafeTime` can be set to when calling `enableFailsafe()`.
       * @returns The failsafe time
       * @throws `PhidgetError`
       */
      getMaxFailsafeTime() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 40:
          case 41:
          case 45:
          case 46:
          case 472:
          case 401:
          case 402:
          case 409:
          case 411:
          case 412:
          case 414:
          case 415:
          case 416:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.maxFailsafeTime === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxFailsafeTime;
      }
      /**
       * The `frequency` parameter sets the PWM frequency for all frequency-settable PWM outputs on the board.
       * @returns The PWM frequency
       * @throws `PhidgetError`
       */
      getFrequency() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 402:
          case 412:
          case 415:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.frequency === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.frequency;
      }
      /**
       * The `frequency` parameter sets the PWM frequency for all frequency-settable PWM outputs on the board.
       * @throws `PhidgetError`
       * @param frequency - The PWM frequency
       */
      async setFrequency(frequency) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: frequency
        });
        await bp.send(this._ch, 156);
      }
      /**
       * The minimum value that `frequency` can be set to.
       * @returns The frequency
       * @throws `PhidgetError`
       */
      getMinFrequency() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 402:
          case 412:
          case 415:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.minFrequency === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minFrequency;
      }
      /**
       * The maximum value that `frequency` can be set to.
       * @returns The frequency
       * @throws `PhidgetError`
       */
      getMaxFrequency() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 402:
          case 412:
          case 415:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.maxFrequency === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxFrequency;
      }
      /**
       * The `LEDCurrentLimit` is the maximum amount of current that the controller will provide to the output.
       *
       * *   Reference the data sheet of the LED you are using before setting this value.
       * @returns The current limit value
       * @throws `PhidgetError`
       */
      getLEDCurrentLimit() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 85:
          case 86:
          case 87:
          case 348:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.LEDCurrentLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.LEDCurrentLimit;
      }
      /**
       * The `LEDCurrentLimit` is the maximum amount of current that the controller will provide to the output.
       *
       * *   Reference the data sheet of the LED you are using before setting this value.
       * @throws `PhidgetError`
       * @param LEDCurrentLimit - The current limit value
       */
      async setLEDCurrentLimit(LEDCurrentLimit) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: LEDCurrentLimit
        });
        await bp.send(this._ch, 67);
      }
      /**
       * The minimum value that `LEDCurrentLimit` can be set to.
       * @returns The current limit value
       * @throws `PhidgetError`
       */
      getMinLEDCurrentLimit() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 85:
          case 86:
          case 87:
          case 348:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.minLEDCurrentLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minLEDCurrentLimit;
      }
      /**
       * The maximum value that `LEDCurrentLimit` can be set to.
       * @returns The current limit value
       * @throws `PhidgetError`
       */
      getMaxLEDCurrentLimit() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 85:
          case 86:
          case 87:
          case 348:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.maxLEDCurrentLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxLEDCurrentLimit;
      }
      /**
       * The `LEDForwardVoltage` is the voltage that will be available to your LED.
       *
       * *   Reference the data sheet of the LED you are using before setting this value. Choose the `LEDForwardVoltage` that is closest to the forward voltage specified in the data sheet.
       * *   This forward voltage is shared for all channels on this device. Setting the LEDForwardVoltage on any channel will set the LEDForwardVoltage for all channels on the device.
       * @returns The forward voltage value
       * @throws `PhidgetError`
       */
      getLEDForwardVoltage() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 85:
          case 86:
          case 87:
          case 348:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.LEDForwardVoltage === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.LEDForwardVoltage;
      }
      /**
       * The `LEDForwardVoltage` is the voltage that will be available to your LED.
       *
       * *   Reference the data sheet of the LED you are using before setting this value. Choose the `LEDForwardVoltage` that is closest to the forward voltage specified in the data sheet.
       * *   This forward voltage is shared for all channels on this device. Setting the LEDForwardVoltage on any channel will set the LEDForwardVoltage for all channels on the device.
       * @throws `PhidgetError`
       * @param LEDForwardVoltage - The forward voltage value
       */
      async setLEDForwardVoltage(LEDForwardVoltage) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: LEDForwardVoltage
        });
        await bp.send(this._ch, 68);
      }
      /**
       * Resets the failsafe timer, if one has been set. See `enableFailsafe()` for details.
       *
       * This function will fail if no failsafe timer has been set for the channel.
       * @throws `PhidgetError`
       */
      async resetFailsafe() {
        this._assertOpen();
        const bp = new BridgePacket();
        await bp.send(this._ch, 147);
      }
      /**
       * The `state` will indicate whether the output is high (TRUE) or low (FALSE).
       *
       * *   If a `dutyCycle` has been set, the state will return as TRUE if the DutyCycle is above 0.5, or FALSE otherwise.
       * @returns The state value
       * @throws `PhidgetError`
       */
      getState() {
        this._assertOpen();
        if (this.data.state === 2) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return !!this.data.state;
      }
      /**
       * The `state` will dictate whether the output is constantly high (TRUE) or low (FALSE).
       *
       * *   This will override any `dutyCycle` that may have been set on the channel.
       * *   Setting the `state` to TRUE is the same as setting `dutyCycle` to 1.0, and setting the `state` to FALSE is the same as setting a `dutyCycle` of 0.0.
       * @throws `PhidgetError`
       * @param state - The state value
       */
      async setState(state) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: state ? 1 : 0
        });
        await bp.send(this._ch, 82);
      }
    }

    /** @public */
    class DigitalOutput extends DigitalOutputBase {
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 202:
            this.data.dataAdapterVoltage = bp.entries[0].v;
            this._FIREPropertyChange('DataAdapterVoltage', bp);
            break;
          case 55:
            this.data.state = bp.getNumber(0) ? 1 : 0;
            super._bridgeInput(bp);
            break;
          case 82:
            this.data.dutyCycle = bp.getBoolean(0) ? 1 : 0;
            super._bridgeInput(bp);
            break;
          default:
            super._bridgeInput(bp);
            break;
        }
      }
      /** @internal */
      _errorHandler(code) {
        switch (code) {
          case exports.ErrorEventCode.FAILSAFE_CONDITION:
            this.data.state = 0;
            this.data.dutyCycle = 0;
            break;
          case exports.ErrorEventCode.INVALID_STATE_CONDITION:
            this.data.state = 2;
            this.data.dutyCycle = 1e+300;
            break;
        }
      }
    }

    /**
     * The Distance Sensor class gathers data from the distance sensor on a Phidget board.
     *
     * If you're using a simple 0-5V sensor that does not have its own firmware, use the VoltageInput or VoltageRatioInput class instead, as specified for your device.
     * @public
     */
    class DistanceSensorBase extends PhidgetChannel {
      /** @internal */
      data;
      onDistanceChange = null;
      /** @internal */
      _gotDistanceChangeErrorEvent;
      onSonarReflectionsUpdate = null;
      /** @internal */
      _gotSonarReflectionsUpdateErrorEvent;
      constructor(ch) {
        super(ch);
        this._class = exports.ChannelClass.DISTANCE_SENSOR;
        this.name = "DistanceSensor";
        this.data = this._initData();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 54:
            if (bp.entryCount > 1) this.data.dataInterval = bp.entries[1].v;else this.data.dataInterval = bp.entries[0].v;
            this._FIREPropertyChange('DataInterval', bp);
            this._FIREPropertyChange('DataRate', bp);
            break;
          case 46:
            this.data.distanceChangeTrigger = bp.entries[0].v;
            this._FIREPropertyChange('DistanceChangeTrigger', bp);
            break;
          case 75:
            this.data.sonarQuietMode = bp.entries[0].v;
            this._FIREPropertyChange('SonarQuietMode', bp);
            break;
          case 12:
            {
              this.data.distance = bp.entries[0].v;
              if (this._isAttachedDone && this.onDistanceChange) {
                try {
                  this.onDistanceChange(this.data.distance);
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          case 88:
            {
              if (this._isAttachedDone && this.onSonarReflectionsUpdate) {
                try {
                  this.onSonarReflectionsUpdate(bp.entries[0].v, bp.entries[1].v, bp.entries[2].v);
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          default:
            throw new PhidgetError(exports.ErrorCode.INVALID_PACKET, "Unsupported bridge packet: 0x" + bp.vpkt.toString(16));
        }
      }
      /** @internal */
      _initData() {
        return {
          amplitudes: [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295],
          distances: [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295],
          count: 0,
          dataInterval: 1e+300,
          maxDataInterval: 4294967295,
          minDataRate: 1e+300,
          maxDataRate: 1e+300,
          maxDistance: 4294967295,
          maxDistanceChangeTrigger: 4294967295,
          minDataInterval: 4294967295,
          minDistance: 4294967295,
          minDistanceChangeTrigger: 4294967295,
          distance: 4294967295,
          distanceChangeTrigger: 4294967295,
          sonarQuietMode: 2
        };
      }
      /** @internal */
      _initAfterOpen() {}
      /** @internal */
      async _setDefaults() {}
      /** @internal */
      _hasInitialState() {
        return true;
      }
      /** @internal */
      _fireInitialEvents() {}
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between events can also be affected by the `distanceChangeTrigger`.
       * @throws `PhidgetError`
       */
      get dataInterval() {
        return this.getDataInterval();
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get minDataInterval() {
        return this.getMinDataInterval();
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataInterval() {
        return this.getMaxDataInterval();
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       */
      get dataRate() {
        return this.getDataRate();
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get minDataRate() {
        return this.getMinDataRate();
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataRate() {
        return this.getMaxDataRate();
      }
      /**
       * The most recent distance value that the channel has reported.
       *
       * *   This value will always be between `minDistance` and `maxDistance`.
       * @throws `PhidgetError`
       */
      get distance() {
        return this.getDistance();
      }
      /**
       * The minimum distance that a event will report.
       * @throws `PhidgetError`
       */
      get minDistance() {
        return this.getMinDistance();
      }
      /**
       * The maximum distance that a event will report.
       * @throws `PhidgetError`
       */
      get maxDistance() {
        return this.getMaxDistance();
      }
      /**
       * The channel will not issue an event until the distance value has changed by the amount specified by the `distanceChangeTrigger`.
       *
       * *   Setting the `distanceChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering,
       * @throws `PhidgetError`
       */
      get distanceChangeTrigger() {
        return this.getDistanceChangeTrigger();
      }
      /**
       * The minimum value that `distanceChangeTrigger` can be set to.
       * @throws `PhidgetError`
       */
      get minDistanceChangeTrigger() {
        return this.getMinDistanceChangeTrigger();
      }
      /**
       * The maximum value that `distanceChangeTrigger` can be set to.
       * @throws `PhidgetError`
       */
      get maxDistanceChangeTrigger() {
        return this.getMaxDistanceChangeTrigger();
      }
      /**
       * When set to true, the device will operate more quietly.
       *
       * *   The measurable range is reduced when operating in quiet mode.
       * @throws `PhidgetError`
       */
      get sonarQuietMode() {
        return this.getSonarQuietMode();
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between events can also be affected by the `distanceChangeTrigger`.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getDataInterval() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.dataInterval;
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between events can also be affected by the `distanceChangeTrigger`.
       * @throws `PhidgetError`
       * @param dataInterval - The data interval value
       */
      async setDataInterval(dataInterval) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: dataInterval
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMinDataInterval() {
        this._assertOpen();
        if (this.data.minDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataInterval;
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMaxDataInterval() {
        this._assertOpen();
        if (this.data.maxDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @returns The data rate for the channel
       * @throws `PhidgetError`
       */
      getDataRate() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return 1000.0 / this.data.dataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       * @param dataRate - The data rate for the channel
       */
      async setDataRate(dataRate) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: Math.round(1000.0 / dataRate)
        });
        bp.set({
          name: "1",
          type: "g",
          value: 1000.0 / dataRate
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMinDataRate() {
        this._assertOpen();
        if (this.data.minDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataRate;
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMaxDataRate() {
        this._assertOpen();
        if (this.data.maxDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataRate;
      }
      /**
       * The most recent distance value that the channel has reported.
       *
       * *   This value will always be between `minDistance` and `maxDistance`.
       * @returns The distance value
       * @throws `PhidgetError`
       */
      getDistance() {
        this._assertOpen();
        if (this.data.distance === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        if (this.data.distance > this.data.maxDistance) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE_HIGH);
        if (this.data.distance < this.data.minDistance) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE_LOW);
        return this.data.distance;
      }
      /**
       * The minimum distance that a event will report.
       * @returns The distance value
       * @throws `PhidgetError`
       */
      getMinDistance() {
        this._assertOpen();
        if (this.data.minDistance === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDistance;
      }
      /**
       * The maximum distance that a event will report.
       * @returns The distance value
       * @throws `PhidgetError`
       */
      getMaxDistance() {
        this._assertOpen();
        if (this.data.maxDistance === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDistance;
      }
      /**
       * The channel will not issue an event until the distance value has changed by the amount specified by the `distanceChangeTrigger`.
       *
       * *   Setting the `distanceChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering,
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getDistanceChangeTrigger() {
        this._assertOpen();
        if (this.data.distanceChangeTrigger === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.distanceChangeTrigger;
      }
      /**
       * The channel will not issue an event until the distance value has changed by the amount specified by the `distanceChangeTrigger`.
       *
       * *   Setting the `distanceChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering,
       * @throws `PhidgetError`
       * @param distanceChangeTrigger - The change trigger value
       */
      async setDistanceChangeTrigger(distanceChangeTrigger) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: distanceChangeTrigger
        });
        await bp.send(this._ch, 46);
      }
      /**
       * The minimum value that `distanceChangeTrigger` can be set to.
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getMinDistanceChangeTrigger() {
        this._assertOpen();
        if (this.data.minDistanceChangeTrigger === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDistanceChangeTrigger;
      }
      /**
       * The maximum value that `distanceChangeTrigger` can be set to.
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getMaxDistanceChangeTrigger() {
        this._assertOpen();
        if (this.data.maxDistanceChangeTrigger === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDistanceChangeTrigger;
      }
      /**
       * When set to true, the device will operate more quietly.
       *
       * *   The measurable range is reduced when operating in quiet mode.
       * @returns The quiet mode value
       * @throws `PhidgetError`
       */
      getSonarQuietMode() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 316:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.sonarQuietMode === 2) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return !!this.data.sonarQuietMode;
      }
      /**
       * When set to true, the device will operate more quietly.
       *
       * *   The measurable range is reduced when operating in quiet mode.
       * @throws `PhidgetError`
       * @param sonarQuietMode - The quiet mode value
       */
      async setSonarQuietMode(sonarQuietMode) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: sonarQuietMode ? 1 : 0
        });
        await bp.send(this._ch, 75);
      }
    }

    /** @public */
    class DistanceSensor extends DistanceSensorBase {
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 88:
            this.data.distances = bp.getArray(0);
            this.data.amplitudes = bp.getArray(1);
            this.data.count = bp.getNumber(2);
            super._bridgeInput(bp);
            break;
          default:
            super._bridgeInput(bp);
            break;
        }
      }
      /** @internal */
      _errorHandler(code) {
        switch (code) {
          case exports.ErrorEventCode.SATURATION:
          case exports.ErrorEventCode.OUT_OF_RANGE:
            this.data.distance = 4294967295;
            this._gotDistanceChangeErrorEvent = true;
            break;
        }
      }
      getSonarReflections() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 316:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        return {
          distances: this.data.distances,
          amplitudes: this.data.amplitudes,
          count: this.data.count
        };
      }
    }

    /**
     * The Encoder class is used to read position data from quadrature encoders in order to track linear or rotary movement. If the device supports an index pin as a reference point, you can also access it through this class.
     * @public
     */
    class EncoderBase extends PhidgetChannel {
      /** @internal */
      data;
      onPositionChange = null;
      /** @internal */
      _gotPositionChangeErrorEvent;
      constructor(ch) {
        super(ch);
        this._class = exports.ChannelClass.ENCODER;
        this.name = "Encoder";
        this.data = this._initData();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 54:
            if (bp.entryCount > 1) this.data.dataInterval = bp.entries[1].v;else this.data.dataInterval = bp.entries[0].v;
            this._FIREPropertyChange('DataInterval', bp);
            this._FIREPropertyChange('DataRate', bp);
            break;
          case 56:
            this.data.enabled = bp.entries[0].v;
            this._FIREPropertyChange('Enabled', bp);
            break;
          case 65:
            this.data.IOMode = bp.entries[0].v;
            this._FIREPropertyChange('IOMode', bp);
            break;
          case 46:
            this.data.positionChangeTrigger = bp.entries[0].v;
            this._FIREPropertyChange('PositionChangeTrigger', bp);
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.INVALID_PACKET, "Unsupported bridge packet: 0x" + bp.vpkt.toString(16));
        }
      }
      /** @internal */
      _initData() {
        return {
          dataInterval: 1e+300,
          minDataInterval: 4294967295,
          maxDataInterval: 4294967295,
          minDataRate: 1e+300,
          maxDataRate: 1e+300,
          maxPositionChangeTrigger: 4294967295,
          minPositionChangeTrigger: 4294967295,
          position: 9223372036854776000,
          indexPosition: 9223372036854776000,
          positionChangeTrigger: 4294967295,
          enabled: 2,
          IOMode: 2147483647
        };
      }
      /** @internal */
      _initAfterOpen() {}
      /** @internal */
      async _setDefaults() {}
      /** @internal */
      _hasInitialState() {
        return true;
      }
      /** @internal */
      _fireInitialEvents() {}
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `PositionChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between `PositionChange` events can also be affected by the `positionChangeTrigger`.
       * @throws `PhidgetError`
       */
      get dataInterval() {
        return this.getDataInterval();
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get minDataInterval() {
        return this.getMinDataInterval();
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataInterval() {
        return this.getMaxDataInterval();
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       */
      get dataRate() {
        return this.getDataRate();
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get minDataRate() {
        return this.getMinDataRate();
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataRate() {
        return this.getMaxDataRate();
      }
      /**
       * The enabled state of the encoder.
       * @throws `PhidgetError`
       */
      get enabled() {
        return this.getEnabled();
      }
      /**
       * The most recent position of the index channel calculated by the Phidgets library.
       *
       * *   The index channel will usually pulse once per rotation.
       * *   Setting the encoder position will move the index position the same amount so their relative position stays the same.
       * *   Index position is tracked locally as the last position at which the index was triggered. Setting position will only affect the local copy of the index position value. This means that index positions seen by multiple network applications may not agree.
       * @throws `PhidgetError`
       */
      get indexPosition() {
        return this.getIndexPosition();
      }
      /**
       * The encoder interface mode. Match the mode to the type of encoder you have attached.
       *
       * *   It is recommended to only change this when the encoder disabled in order to avoid unexpected results.
       * @throws `PhidgetError`
       */
      get IOMode() {
        return this.getIOMode();
      }
      /**
       * The most recent position value calculated by the Phidgets library.
       *
       * *   Position counts quadrature edges within a quadrature cycle. This means there are four counts per full quadrature cycle.
       * *   Position is tracked locally as the total position change from the time the channel is opened. Setting position will only affect the local copy of the position value. This means that positions seen by multiple network applications may not agree.
       * @throws `PhidgetError`
       */
      get position() {
        return this.getPosition();
      }
      set position(position) {
        this.setPosition(position);
      }
      /**
       * The channel will not issue a `PositionChange` event until the position value has changed by the amount specified by the `positionChangeTrigger`.
       *
       * *   Setting the `positionChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @throws `PhidgetError`
       */
      get positionChangeTrigger() {
        return this.getPositionChangeTrigger();
      }
      /**
       * The minimum value that `positionChangeTrigger` can be set to.
       * @throws `PhidgetError`
       */
      get minPositionChangeTrigger() {
        return this.getMinPositionChangeTrigger();
      }
      /**
       * The maximum value that `positionChangeTrigger` can be set to.
       * @throws `PhidgetError`
       */
      get maxPositionChangeTrigger() {
        return this.getMaxPositionChangeTrigger();
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `PositionChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between `PositionChange` events can also be affected by the `positionChangeTrigger`.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getDataInterval() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.dataInterval;
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `PositionChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between `PositionChange` events can also be affected by the `positionChangeTrigger`.
       * @throws `PhidgetError`
       * @param dataInterval - The data interval value
       */
      async setDataInterval(dataInterval) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: dataInterval
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMinDataInterval() {
        this._assertOpen();
        if (this.data.minDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataInterval;
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMaxDataInterval() {
        this._assertOpen();
        if (this.data.maxDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @returns The data rate for the channel
       * @throws `PhidgetError`
       */
      getDataRate() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return 1000.0 / this.data.dataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       * @param dataRate - The data rate for the channel
       */
      async setDataRate(dataRate) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: Math.round(1000.0 / dataRate)
        });
        bp.set({
          name: "1",
          type: "g",
          value: 1000.0 / dataRate
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMinDataRate() {
        this._assertOpen();
        if (this.data.minDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataRate;
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMaxDataRate() {
        this._assertOpen();
        if (this.data.maxDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataRate;
      }
      /**
       * The enabled state of the encoder.
       * @returns The enabled value
       * @throws `PhidgetError`
       */
      getEnabled() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 276:
          case 283:
          case 299:
          case 306:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.enabled === 2) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return !!this.data.enabled;
      }
      /**
       * The enabled state of the encoder.
       * @throws `PhidgetError`
       * @param enabled - The enabled value
       */
      async setEnabled(enabled) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: enabled ? 1 : 0
        });
        await bp.send(this._ch, 56);
      }
      /**
       * The most recent position of the index channel calculated by the Phidgets library.
       *
       * *   The index channel will usually pulse once per rotation.
       * *   Setting the encoder position will move the index position the same amount so their relative position stays the same.
       * *   Index position is tracked locally as the last position at which the index was triggered. Setting position will only affect the local copy of the index position value. This means that index positions seen by multiple network applications may not agree.
       * @returns The index position value
       * @throws `PhidgetError`
       */
      getIndexPosition() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 136:
          case 138:
          case 140:
          case 153:
          case 324:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.indexPosition === 9223372036854776000) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.indexPosition;
      }
      /**
       * The encoder interface mode. Match the mode to the type of encoder you have attached.
       *
       * *   It is recommended to only change this when the encoder disabled in order to avoid unexpected results.
       * @returns The IO mode value.
       * @throws `PhidgetError`
       */
      getIOMode() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 154:
          case 246:
          case 251:
          case 257:
          case 317:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.IOMode === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.IOMode;
      }
      /**
       * The encoder interface mode. Match the mode to the type of encoder you have attached.
       *
       * *   It is recommended to only change this when the encoder disabled in order to avoid unexpected results.
       * @throws `PhidgetError`
       * @param IOMode - The IO mode value.
       */
      async setIOMode(IOMode) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: IOMode
        });
        await bp.send(this._ch, 65);
      }
      /**
       * The most recent position value calculated by the Phidgets library.
       *
       * *   Position counts quadrature edges within a quadrature cycle. This means there are four counts per full quadrature cycle.
       * *   Position is tracked locally as the total position change from the time the channel is opened. Setting position will only affect the local copy of the position value. This means that positions seen by multiple network applications may not agree.
       * @returns The position value
       * @throws `PhidgetError`
       */
      getPosition() {
        this._assertOpen();
        if (this.data.position === 9223372036854776000) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.position;
      }
      /**
       * The channel will not issue a `PositionChange` event until the position value has changed by the amount specified by the `positionChangeTrigger`.
       *
       * *   Setting the `positionChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getPositionChangeTrigger() {
        this._assertOpen();
        if (this.data.positionChangeTrigger === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.positionChangeTrigger;
      }
      /**
       * The channel will not issue a `PositionChange` event until the position value has changed by the amount specified by the `positionChangeTrigger`.
       *
       * *   Setting the `positionChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @throws `PhidgetError`
       * @param positionChangeTrigger - The change trigger value
       */
      async setPositionChangeTrigger(positionChangeTrigger) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: positionChangeTrigger
        });
        await bp.send(this._ch, 46);
      }
      /**
       * The minimum value that `positionChangeTrigger` can be set to.
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getMinPositionChangeTrigger() {
        this._assertOpen();
        if (this.data.minPositionChangeTrigger === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minPositionChangeTrigger;
      }
      /**
       * The maximum value that `positionChangeTrigger` can be set to.
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getMaxPositionChangeTrigger() {
        this._assertOpen();
        if (this.data.maxPositionChangeTrigger === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxPositionChangeTrigger;
      }
    }

    /** @public */
    class Encoder extends EncoderBase {
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 10:
            {
              if (bp.entryCount > 1) this.data.dataInterval = bp.getNumber(1);else this.data.dataInterval = bp.getNumber(0);
              this._FIREPropertyChange('DataInterval');
              this._FIREPropertyChange('DataRate');
              break;
            }
          case 29:
            {
              const positionChange = bp.getNumber(0);
              const timeChange = bp.getNumber(1);
              const indexTriggered = bp.getBoolean(2);
              if (indexTriggered) this.data.indexPosition = this.data.position + bp.getNumber(3);
              this.data.position += positionChange;
              if (this._isAttachedDone && this.onPositionChange) {
                try {
                  this.onPositionChange(positionChange, timeChange, indexTriggered);
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          default:
            super._bridgeInput(bp);
            break;
        }
      }
      setPosition(position) {
        this._assertOpen();
        if (this.data.indexPosition != 9223372036854776000) this.data.indexPosition += position - this.data.position;
        this.data.position = position;
      }
    }

    /**
     * @internal
     */
    class FirmwareUpgradeBase extends PhidgetChannel {
      /** @internal */
      data;
      /**
       * **ProgressChange** event
       *
       *  * `progress` - The progress, range is 0-1.
       * ---
       * Occurs on firmware upgrade progress.
       * @internal
       */
      onProgressChange = null;
      /** @internal */
      _gotProgressChangeErrorEvent;
      constructor(ch) {
        super(ch);
        this._class = exports.ChannelClass.FIRMWARE_UPGRADE;
        this.name = "FirmwareUpgrade";
        this.data = this._initData();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 112:
            break;
          case 113:
            {
              this.data.progress = bp.entries[0].v;
              if (this._isAttachedDone && this.onProgressChange) {
                try {
                  this.onProgressChange(this.data.progress);
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          default:
            throw new PhidgetError(exports.ErrorCode.INVALID_PACKET, "Unsupported bridge packet: 0x" + bp.vpkt.toString(16));
        }
      }
      /** @internal */
      _initData() {
        return {
          actualDeviceID: 2147483647,
          actualDeviceVINTID: 4294967295,
          actualDeviceSKU: null,
          actualDeviceVersion: 2147483647,
          actualDeviceName: null,
          progress: 1e+300
        };
      }
      /** @internal */
      _initAfterOpen() {}
      /** @internal */
      async _setDefaults() {}
      /** @internal */
      _hasInitialState() {
        return true;
      }
      /** @internal */
      _fireInitialEvents() {}
      /**
       * The Device ID of the actual device being upgraded.
       * @throws `PhidgetError`
       * @internal
       */
      get actualDeviceID() {
        return this.getActualDeviceID();
      }
      /**
       * The name of the actual device being upgraded.
       * @throws `PhidgetError`
       * @internal
       */
      get actualDeviceName() {
        return this.getActualDeviceName();
      }
      /**
       * The SKU of the actual device being upgraded.
       * @throws `PhidgetError`
       * @internal
       */
      get actualDeviceSKU() {
        return this.getActualDeviceSKU();
      }
      /**
       * The firmware version of the actual device being upgraded.
       * @throws `PhidgetError`
       * @internal
       */
      get actualDeviceVersion() {
        return this.getActualDeviceVersion();
      }
      /**
       * The VINT ID of the actual device being upgraded.
       * @throws `PhidgetError`
       * @internal
       */
      get actualDeviceVINTID() {
        return this.getActualDeviceVINTID();
      }
      /**
       * The progress of the firmware update, ranging from 0 to 1.
       * @throws `PhidgetError`
       * @internal
       */
      get progress() {
        return this.getProgress();
      }
      /**
       * The Device ID of the actual device being upgraded.
       * @returns Device ID
       * @throws `PhidgetError`
       * @internal
       */
      getActualDeviceID() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 480:
          case 481:
          case 486:
          case 489:
          case 485:
          case 479:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.actualDeviceID === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.actualDeviceID;
      }
      /**
       * The name of the actual device being upgraded.
       * @returns Name of the device
       * @throws `PhidgetError`
       * @internal
       */
      getActualDeviceName() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 480:
          case 481:
          case 486:
          case 489:
          case 485:
          case 479:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.actualDeviceName === null) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.actualDeviceName;
      }
      /**
       * The SKU of the actual device being upgraded.
       * @returns Device SKU
       * @throws `PhidgetError`
       * @internal
       */
      getActualDeviceSKU() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 480:
          case 481:
          case 486:
          case 489:
          case 485:
          case 479:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.actualDeviceSKU === null) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.actualDeviceSKU;
      }
      /**
       * The firmware version of the actual device being upgraded.
       * @returns Firmware version
       * @throws `PhidgetError`
       * @internal
       */
      getActualDeviceVersion() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 480:
          case 481:
          case 486:
          case 489:
          case 485:
          case 479:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.actualDeviceVersion === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.actualDeviceVersion;
      }
      /**
       * The VINT ID of the actual device being upgraded.
       * @returns Device VINT ID
       * @throws `PhidgetError`
       * @internal
       */
      getActualDeviceVINTID() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 480:
          case 481:
          case 486:
          case 489:
          case 485:
          case 479:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.actualDeviceVINTID === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.actualDeviceVINTID;
      }
      /**
       * The progress of the firmware update, ranging from 0 to 1.
       * @returns Firmware update progress
       * @throws `PhidgetError`
       * @internal
       */
      getProgress() {
        this._assertOpen();
        if (this.data.progress === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.progress;
      }
    }

    /** @internal */
    class FirmwareUpgrade extends FirmwareUpgradeBase {
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 114:
            break;
          default:
            super._bridgeInput(bp);
            break;
        }
      }
      /** @internal */
      sendFirmware(_data) {
        throw new Error('Method not implemented.');
      }
    }

    /**
     * The Frequency Counter class is used to measure the frequency of pulses in an electronic signal, or to count the pulses in the signal. Such signals can come from other electronics, or certain sensors that have a pulse output.
     * @public
     */
    class FrequencyCounterBase extends PhidgetChannel {
      /** @internal */
      data;
      onFrequencyChange = null;
      /** @internal */
      _gotFrequencyChangeErrorEvent;
      onCountChange = null;
      /** @internal */
      _gotCountChangeErrorEvent;
      constructor(ch) {
        super(ch);
        this._class = exports.ChannelClass.FREQUENCY_COUNTER;
        this.name = "FrequencyCounter";
        this.data = this._initData();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 54:
            if (bp.entryCount > 1) this.data.dataInterval = bp.entries[1].v;else this.data.dataInterval = bp.entries[0].v;
            this._FIREPropertyChange('DataInterval', bp);
            this._FIREPropertyChange('DataRate', bp);
            break;
          case 56:
            this.data.enabled = bp.entries[0].v;
            this._FIREPropertyChange('Enabled', bp);
            break;
          case 59:
            this.data.filterType = bp.entries[0].v;
            this._FIREPropertyChange('FilterType', bp);
            break;
          case 220:
            this.data.frequencyCutoff = bp.entries[0].v;
            this._FIREPropertyChange('FrequencyCutoff', bp);
            break;
          case 64:
            this.data.inputMode = bp.entries[0].v;
            this._FIREPropertyChange('InputMode', bp);
            break;
          case 74:
            this.data.powerSupply = bp.entries[0].v;
            this._FIREPropertyChange('PowerSupply', bp);
            break;
          case 7:
            {
              if (this._isAttachedDone && this.onCountChange) {
                try {
                  this.onCountChange(bp.entries[0].v, bp.entries[1].v);
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          case 21:
            {
              this.data.frequency = bp.entries[0].v;
              if (this._isAttachedDone && this.onFrequencyChange) {
                try {
                  this.onFrequencyChange(this.data.frequency);
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          default:
            throw new PhidgetError(exports.ErrorCode.INVALID_PACKET, "Unsupported bridge packet: 0x" + bp.vpkt.toString(16));
        }
      }
      /** @internal */
      _initData() {
        return {
          totalTicksSinceLastCount: 0,
          frequencyPrecision: 0,
          dataInterval: 1e+300,
          minDataInterval: 4294967295,
          maxDataInterval: 4294967295,
          minDataRate: 1e+300,
          maxDataRate: 1e+300,
          maxFrequency: 1e+300,
          maxFrequencyCutoff: 1e+300,
          minFrequencyCutoff: 1e+300,
          count: 18446744073709552000,
          timeElapsed: 1e+300,
          frequencyCutoff: 1e+300,
          frequency: 1e+300,
          filterType: 2147483647,
          powerSupply: 2147483647,
          inputMode: 2147483647,
          enabled: 2
        };
      }
      /** @internal */
      _initAfterOpen() {}
      /** @internal */
      async _setDefaults() {}
      /** @internal */
      _hasInitialState() {
        return true;
      }
      /** @internal */
      _fireInitialEvents() {}
      /**
       * The most recent count value the channel has reported.
       *
       * *   The count represents the total number of pulses since the the channel was opened, or last reset.
       * @throws `PhidgetError`
       */
      get count() {
        return this.getCount();
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `CountChange` / `FrequencyChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * @throws `PhidgetError`
       */
      get dataInterval() {
        return this.getDataInterval();
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get minDataInterval() {
        return this.getMinDataInterval();
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataInterval() {
        return this.getMaxDataInterval();
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       */
      get dataRate() {
        return this.getDataRate();
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get minDataRate() {
        return this.getMinDataRate();
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataRate() {
        return this.getMaxDataRate();
      }
      /**
       * Enables or disables the channel.
       *
       * *   When a channel is disabled, it will not longer register counts, therefore the `timeElapsed` and `count` will not be updated until the channel is re-enabled.
       * @throws `PhidgetError`
       */
      get enabled() {
        return this.getEnabled();
      }
      /**
       * Determines the signal type that the channel responds to.
       *
       * *   The filter type is chosen based on the type of input signal. See the `phidget22.FrequencyFilterType` entry under Enumerations for more information.
       * @throws `PhidgetError`
       */
      get filterType() {
        return this.getFilterType();
      }
      /**
       * The most recent frequency value that the channel has reported.
       *
       * *   This value will always be between 0 Hz and `maxFrequency`.
       * @throws `PhidgetError`
       */
      get frequency() {
        return this.getFrequency();
      }
      /**
       * The maximum value the `FrequencyChange` event will report.
       * @throws `PhidgetError`
       */
      get maxFrequency() {
        return this.getMaxFrequency();
      }
      /**
       * The frequency at which zero hertz is assumed.
       *
       * *   This means any frequency at or below the `frequencyCutoff` value will be reported as 0 Hz.
       * *   This property is stored locally, so other users who have this Phidget open over a network connection won't see the effects of your selected cutoff.
       * @throws `PhidgetError`
       */
      get frequencyCutoff() {
        return this.getFrequencyCutoff();
      }
      /**
       * The minimum value that `frequencyCutoff` can be set to.
       * @throws `PhidgetError`
       */
      get minFrequencyCutoff() {
        return this.getMinFrequencyCutoff();
      }
      /**
       * The maximum value that `frequencyCutoff` can be set to.
       * @throws `PhidgetError`
       */
      get maxFrequencyCutoff() {
        return this.getMaxFrequencyCutoff();
      }
      /**
       * The input polarity mode for your channel.
       *
       * *   See your device's User Guide for more information about what value to chooose for the `inputMode`
       * @throws `PhidgetError`
       */
      get inputMode() {
        return this.getInputMode();
      }
      /**
       * Choose the power supply voltage.
       *
       * *   Set this to the voltage specified in the attached sensor's data sheet to power it.
       * *   Set to `phidget22.PowerSupply.OFF` to turn off the supply to save power.
       * @throws `PhidgetError`
       */
      get powerSupply() {
        return this.getPowerSupply();
      }
      /**
       * The amount of time the frequency counter has been enabled for.
       *
       * *   This property complements `count`, the total number of pulses detected since the channel was opened, or last reset.
       * @throws `PhidgetError`
       */
      get timeElapsed() {
        return this.getTimeElapsed();
      }
      /**
       * The most recent count value the channel has reported.
       *
       * *   The count represents the total number of pulses since the the channel was opened, or last reset.
       * @returns The count value
       * @throws `PhidgetError`
       */
      getCount() {
        this._assertOpen();
        if (this.data.count === 18446744073709552000) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.count;
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `CountChange` / `FrequencyChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getDataInterval() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.dataInterval;
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `CountChange` / `FrequencyChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * @throws `PhidgetError`
       * @param dataInterval - The data interval value
       */
      async setDataInterval(dataInterval) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: dataInterval
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMinDataInterval() {
        this._assertOpen();
        if (this.data.minDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataInterval;
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMaxDataInterval() {
        this._assertOpen();
        if (this.data.maxDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @returns The data rate for the channel
       * @throws `PhidgetError`
       */
      getDataRate() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return 1000.0 / this.data.dataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       * @param dataRate - The data rate for the channel
       */
      async setDataRate(dataRate) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: Math.round(1000.0 / dataRate)
        });
        bp.set({
          name: "1",
          type: "g",
          value: 1000.0 / dataRate
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMinDataRate() {
        this._assertOpen();
        if (this.data.minDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataRate;
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMaxDataRate() {
        this._assertOpen();
        if (this.data.maxDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataRate;
      }
      /**
       * Enables or disables the channel.
       *
       * *   When a channel is disabled, it will not longer register counts, therefore the `timeElapsed` and `count` will not be updated until the channel is re-enabled.
       * @returns The enabled value
       * @throws `PhidgetError`
       */
      getEnabled() {
        this._assertOpen();
        if (this.data.enabled === 2) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return !!this.data.enabled;
      }
      /**
       * Enables or disables the channel.
       *
       * *   When a channel is disabled, it will not longer register counts, therefore the `timeElapsed` and `count` will not be updated until the channel is re-enabled.
       * @throws `PhidgetError`
       * @param enabled - The enabled value
       */
      async setEnabled(enabled) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: enabled ? 1 : 0
        });
        await bp.send(this._ch, 56);
      }
      /**
       * Determines the signal type that the channel responds to.
       *
       * *   The filter type is chosen based on the type of input signal. See the `phidget22.FrequencyFilterType` entry under Enumerations for more information.
       * @returns The filter value
       * @throws `PhidgetError`
       */
      getFilterType() {
        this._assertOpen();
        if (this.data.filterType === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.filterType;
      }
      /**
       * Determines the signal type that the channel responds to.
       *
       * *   The filter type is chosen based on the type of input signal. See the `phidget22.FrequencyFilterType` entry under Enumerations for more information.
       * @throws `PhidgetError`
       * @param filterType - The filter value
       */
      async setFilterType(filterType) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: filterType
        });
        await bp.send(this._ch, 59);
      }
      /**
       * The most recent frequency value that the channel has reported.
       *
       * *   This value will always be between 0 Hz and `maxFrequency`.
       * @returns The frequency value
       * @throws `PhidgetError`
       */
      getFrequency() {
        this._assertOpen();
        if (this.data.frequency === 1e+300 || Number.isNaN(this.data.frequency)) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        if (this.data.frequency > this.data.maxFrequency) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE_HIGH);
        return this.data.frequency;
      }
      /**
       * The maximum value the `FrequencyChange` event will report.
       * @returns The frequency value
       * @throws `PhidgetError`
       */
      getMaxFrequency() {
        this._assertOpen();
        if (this.data.maxFrequency === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxFrequency;
      }
      /**
       * The minimum value that `frequencyCutoff` can be set to.
       * @returns The frequency value
       * @throws `PhidgetError`
       */
      getMinFrequencyCutoff() {
        this._assertOpen();
        if (this.data.minFrequencyCutoff === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minFrequencyCutoff;
      }
      /**
       * The maximum value that `frequencyCutoff` can be set to.
       * @returns The frequency value
       * @throws `PhidgetError`
       */
      getMaxFrequencyCutoff() {
        this._assertOpen();
        if (this.data.maxFrequencyCutoff === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxFrequencyCutoff;
      }
      /**
       * The input polarity mode for your channel.
       *
       * *   See your device's User Guide for more information about what value to chooose for the `inputMode`
       * @returns The input mode value
       * @throws `PhidgetError`
       */
      getInputMode() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 143:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.inputMode === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.inputMode;
      }
      /**
       * The input polarity mode for your channel.
       *
       * *   See your device's User Guide for more information about what value to chooose for the `inputMode`
       * @throws `PhidgetError`
       * @param inputMode - The input mode value
       */
      async setInputMode(inputMode) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: inputMode
        });
        await bp.send(this._ch, 64);
      }
      /**
       * Choose the power supply voltage.
       *
       * *   Set this to the voltage specified in the attached sensor's data sheet to power it.
       * *   Set to `phidget22.PowerSupply.OFF` to turn off the supply to save power.
       * @returns The power supply value
       * @throws `PhidgetError`
       */
      getPowerSupply() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 143:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.powerSupply === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.powerSupply;
      }
      /**
       * Choose the power supply voltage.
       *
       * *   Set this to the voltage specified in the attached sensor's data sheet to power it.
       * *   Set to `phidget22.PowerSupply.OFF` to turn off the supply to save power.
       * @throws `PhidgetError`
       * @param powerSupply - The power supply value
       */
      async setPowerSupply(powerSupply) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: powerSupply
        });
        await bp.send(this._ch, 74);
      }
      /**
       * The amount of time the frequency counter has been enabled for.
       *
       * *   This property complements `count`, the total number of pulses detected since the channel was opened, or last reset.
       * @returns The time value
       * @throws `PhidgetError`
       */
      getTimeElapsed() {
        this._assertOpen();
        if (this.data.timeElapsed === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.timeElapsed;
      }
    }

    function RoundDouble(num, decimals) {
      return Math.round(num * Math.pow(10, decimals)) / Math.pow(10, decimals);
    }

    /** @public */
    class FrequencyCounter extends FrequencyCounterBase {
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 21:
            {
              const ticks = bp.getNumber(0);
              const counts = bp.getNumber(1);
              const ticksAtLastCount = bp.getNumber(2);
              let cutoffTime;
              let precision;
              let d;
              this.data.timeElapsed += ticks;
              this.data.count += counts;
              if (counts == 0) {
                if (Number.isNaN(this.data.totalTicksSinceLastCount)) return;
                this.data.totalTicksSinceLastCount += ticks;
                cutoffTime = Math.round(1000 / this.data.frequencyCutoff);
                if (this.data.totalTicksSinceLastCount > cutoffTime) {
                  this.data.frequency = 0;
                  if (this._isAttachedDone && this.onCountChange) {
                    try {
                      this.onCountChange(0, this.data.totalTicksSinceLastCount);
                    } catch (err) {
                      logEventException(err);
                    }
                  }
                  if (this._isAttachedDone && this.onFrequencyChange) {
                    try {
                      this.onFrequencyChange(this.data.frequency);
                    } catch (err) {
                      logEventException(err);
                    }
                  }
                  this.data.totalTicksSinceLastCount = Number.NaN;
                }
                return;
              }
              if (Number.isNaN(this.data.totalTicksSinceLastCount)) {
                this.data.totalTicksSinceLastCount = ticks - ticksAtLastCount;
                return;
              }
              const countTimeSpan = this.data.totalTicksSinceLastCount + ticksAtLastCount;
              this.data.totalTicksSinceLastCount = ticks - ticksAtLastCount;
              d = this.data.frequencyCutoff;
              precision = 2;
              while (d < 1) {
                precision++;
                d *= 10;
              }
              this.data.frequency = RoundDouble(counts / (countTimeSpan / 1000.0), precision);
              if (this._isAttachedDone && this.onCountChange) {
                try {
                  this.onCountChange(counts, countTimeSpan);
                } catch (err) {
                  logEventException(err);
                }
              }
              if (this._isAttachedDone && this.onFrequencyChange) {
                try {
                  this.onFrequencyChange(this.data.frequency);
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          case 56:
            if (!bp.getBoolean(0)) this.data.frequency = 1e+300;
            super._bridgeInput(bp);
            break;
          case 181:
            this.data.powerSupply = bp.entries[0].v;
            this._FIREPropertyChange('PowerSupply', bp);
            break;
          case 182:
            this.data.inputMode = bp.entries[0].v;
            this._FIREPropertyChange('InputMode', bp);
            break;
          default:
            super._bridgeInput(bp);
            break;
        }
      }
      async setFrequencyCutoff(frequencyCutoff) {
        this._assertOpen();
        if (frequencyCutoff < this.data.minFrequencyCutoff || frequencyCutoff > this.data.maxFrequencyCutoff) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Value must be in range: " + this.data.minFrequencyCutoff + " - " + this.data.maxFrequencyCutoff + ".");
        switch (this._ch?.chDef.uid) {
          case 221:
          case 219:
            {
              const bp = new BridgePacket();
              bp.set({
                name: "0",
                type: "g",
                value: frequencyCutoff
              });
              await bp.send(this._ch, 220);
              break;
            }
          default:
            this.data.frequencyCutoff = frequencyCutoff;
            break;
        }
      }
      getFrequencyCutoff() {
        this._assertOpen();
        if (this.data.frequencyCutoff === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.frequencyCutoff;
      }
      reset() {
        this._assertOpen();
        this.data.count = 0;
        this.data.timeElapsed = 0;
        this.data.frequency = 1e+300;
      }
    }

    /**
     * @internal
     */
    class GenericBase extends PhidgetChannel {
      /** @internal */
      data;
      constructor(ch) {
        super(ch);
        this._class = exports.ChannelClass.GENERIC;
        this.name = "Generic";
        this.data = this._initData();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          default:
            throw new PhidgetError(exports.ErrorCode.INVALID_PACKET, "Unsupported bridge packet: 0x" + bp.vpkt.toString(16));
        }
      }
      /** @internal */
      _initData() {
        return {};
      }
      /** @internal */
      _initAfterOpen() {}
      /** @internal */
      async _setDefaults() {}
      /** @internal */
      _hasInitialState() {
        return true;
      }
      /** @internal */
      _fireInitialEvents() {}
    }

    /** @internal */
    class Generic extends GenericBase {
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          default:
            super._bridgeInput(bp);
            break;
        }
      }
    }

    /**
     * The GPS class is used to configure and gather data from Phidgets GPS sensors, and gives you access to variables from GPS data packets.
     * @public
     */
    class GPSBase extends PhidgetChannel {
      /** @internal */
      data;
      onPositionChange = null;
      /** @internal */
      _gotPositionChangeErrorEvent;
      onHeadingChange = null;
      /** @internal */
      _gotHeadingChangeErrorEvent;
      onPositionFixStateChange = null;
      /** @internal */
      _gotPositionFixStateChangeErrorEvent;
      constructor(ch) {
        super(ch);
        this._class = exports.ChannelClass.GPS;
        this.name = "GPS";
        this.data = this._initData();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 110:
            {
              this.data.heading = bp.entries[0].v;
              this.data.velocity = bp.entries[1].v;
              if (this._isAttachedDone && this.onHeadingChange) {
                try {
                  this.onHeadingChange(this.data.heading, this.data.velocity);
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          case 29:
            {
              this.data.latitude = bp.entries[0].v;
              this.data.longitude = bp.entries[1].v;
              this.data.altitude = bp.entries[2].v;
              if (this._isAttachedDone && this.onPositionChange) {
                try {
                  this.onPositionChange(this.data.latitude, this.data.longitude, this.data.altitude);
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          case 30:
            {
              this.data.positionFixState = bp.entries[0].v;
              if (this._isAttachedDone && this.onPositionFixStateChange) {
                try {
                  this.onPositionFixStateChange(!!this.data.positionFixState);
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          default:
            throw new PhidgetError(exports.ErrorCode.INVALID_PACKET, "Unsupported bridge packet: 0x" + bp.vpkt.toString(16));
        }
      }
      /** @internal */
      _initData() {
        return {
          altitude: 1e+300,
          date: null,
          heading: 1e+300,
          latitude: 1e+300,
          longitude: 1e+300,
          NMEAData: null,
          positionFixState: 2,
          time: null,
          velocity: 1e+300
        };
      }
      /** @internal */
      _initAfterOpen() {}
      /** @internal */
      async _setDefaults() {}
      /** @internal */
      _hasInitialState() {
        return true;
      }
      /** @internal */
      _fireInitialEvents() {}
      /**
       * The altitude above mean sea level in meters.
       * @throws `PhidgetError`
       */
      get altitude() {
        return this.getAltitude();
      }
      /**
       * The UTC date of the last received position.
       * @throws `PhidgetError`
       */
      get date() {
        return this.getDate();
      }
      /**
       * The current date and time in UTC
       * @throws `PhidgetError`
       */
      get dateAndTime() {
        return this.getDateAndTime();
      }
      /**
       * The current true course over ground of the GPS
       * @throws `PhidgetError`
       */
      get heading() {
        return this.getHeading();
      }
      /**
       * The latitude of the GPS in degrees
       * @throws `PhidgetError`
       */
      get latitude() {
        return this.getLatitude();
      }
      /**
       * The longitude of the GPS.
       * @throws `PhidgetError`
       */
      get longitude() {
        return this.getLongitude();
      }
      /**
       * The NMEA data structure.
       * @throws `PhidgetError`
       */
      get NMEAData() {
        return this.getNMEAData();
      }
      /**
       * The status of the position fix
       *
       * *   True if a fix is available and latitude, longitude, and altitude can be read. False if the fix is not available.
       * @throws `PhidgetError`
       */
      get positionFixState() {
        return this.getPositionFixState();
      }
      /**
       * The current UTC time of the GPS
       * @throws `PhidgetError`
       */
      get time() {
        return this.getTime();
      }
      /**
       * The current speed over ground of the GPS.
       * @throws `PhidgetError`
       */
      get velocity() {
        return this.getVelocity();
      }
      /**
       * The altitude above mean sea level in meters.
       * @returns Altitude of the GPS
       * @throws `PhidgetError`
       */
      getAltitude() {
        this._assertOpen();
        if (this.data.altitude === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.altitude;
      }
      /**
       * The UTC date of the last received position.
       * @returns Date of last position
       * @throws `PhidgetError`
       */
      getDate() {
        this._assertOpen();
        if (this.data.date === null) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.date;
      }
      /**
       * The current true course over ground of the GPS
       * @returns Heading of the GPS
       * @throws `PhidgetError`
       */
      getHeading() {
        this._assertOpen();
        if (this.data.heading === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.heading;
      }
      /**
       * The latitude of the GPS in degrees
       * @returns Latitude of the GPS
       * @throws `PhidgetError`
       */
      getLatitude() {
        this._assertOpen();
        if (this.data.latitude === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.latitude;
      }
      /**
       * The longitude of the GPS.
       * @returns Longtidue of the GPS
       * @throws `PhidgetError`
       */
      getLongitude() {
        this._assertOpen();
        if (this.data.longitude === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.longitude;
      }
      /**
       * The NMEA data structure.
       * @returns NMEA Data structure
       * @throws `PhidgetError`
       */
      getNMEAData() {
        this._assertOpen();
        if (this.data.NMEAData === null) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.NMEAData;
      }
      /**
       * The status of the position fix
       *
       * *   True if a fix is available and latitude, longitude, and altitude can be read. False if the fix is not available.
       * @returns Status of the position fix
       * @throws `PhidgetError`
       */
      getPositionFixState() {
        this._assertOpen();
        if (this.data.positionFixState === 2) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return !!this.data.positionFixState;
      }
      /**
       * The current UTC time of the GPS
       * @returns Current time
       * @throws `PhidgetError`
       */
      getTime() {
        this._assertOpen();
        if (this.data.time === null) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.time;
      }
      /**
       * The current speed over ground of the GPS.
       * @returns Velocity of the GPS
       * @throws `PhidgetError`
       */
      getVelocity() {
        this._assertOpen();
        if (this.data.velocity === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.velocity;
      }
    }

    function readGPGGA(bp) {
      return {
        latitude: bp.getNumber("GPGGA.latitude"),
        longitude: bp.getNumber("GPGGA.longitude"),
        fixQuality: bp.getNumber("GPGGA.fixQuality"),
        numSatellites: bp.getNumber("GPGGA.numSatellites"),
        horizontalDilution: bp.getNumber("GPGGA.horizontalDilution"),
        altitude: bp.getNumber("GPGGA.altitude"),
        heightOfGeoid: bp.getNumber("GPGGA.heightOfGeoid")
      };
    }
    function readGPGSA(bp) {
      return {
        mode: String.fromCharCode(bp.getNumber("GPGSA.mode")),
        fixType: bp.getNumber("GPGSA.fixType"),
        satUsed: bp.getArray("GPGSA.satUsed"),
        posnDilution: bp.getNumber("GPGSA.posnDilution"),
        horizDilution: bp.getNumber("GPGSA.horizDilution"),
        vertDilution: bp.getNumber("GPGSA.vertDilution")
      };
    }
    function readGPRMC(bp) {
      return {
        status: String.fromCharCode(bp.getNumber("GPRMC.status")),
        latitude: bp.getNumber("GPRMC.latitude"),
        longitude: bp.getNumber("GPRMC.longitude"),
        speedKnots: bp.getNumber("GPRMC.speedKnots"),
        heading: bp.getNumber("GPRMC.heading"),
        magneticVariation: bp.getNumber("GPRMC.magneticVariation"),
        mode: String.fromCharCode(bp.getNumber("GPRMC.mode"))
      };
    }
    function readGPVTG(bp) {
      return {
        trueHeading: bp.getNumber("GPVTG.trueHeading"),
        magneticHeading: bp.getNumber("GPVTG.magneticHeading"),
        speedKnots: bp.getNumber("GPVTG.speedKnots"),
        speed: bp.getNumber("GPVTG.speed"),
        mode: String.fromCharCode(bp.getNumber("GPVTG.mode"))
      };
    }
    function readNMEAData(bp) {
      return {
        GGA: readGPGGA(bp),
        GSA: readGPGSA(bp),
        RMC: readGPRMC(bp),
        VTG: readGPVTG(bp)
      };
    }
    /** @public */
    class GPS extends GPSBase {
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 9:
            this.data.NMEAData = readNMEAData(bp);
            break;
          case 108:
            this.data.time = {
              tm_ms: bp.getNumber("GPSTime.tm_ms"),
              tm_sec: bp.getNumber("GPSTime.tm_sec"),
              tm_min: bp.getNumber("GPSTime.tm_min"),
              tm_hour: bp.getNumber("GPSTime.tm_hour")
            };
            break;
          case 109:
            this.data.date = {
              tm_mday: bp.getNumber("GPSDate.tm_mday"),
              tm_mon: bp.getNumber("GPSDate.tm_mon"),
              tm_year: bp.getNumber("GPSDate.tm_year")
            };
            break;
          default:
            super._bridgeInput(bp);
            break;
        }
      }
      getDateAndTime() {
        this._assertOpen();
        if (this.data.time === null) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        if (this.data.date === null) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        const date = new Date(Date.UTC(this.data.date.tm_year, this.data.date.tm_mon, this.data.date.tm_mday, this.data.time.tm_hour, this.data.time.tm_min, this.data.time.tm_sec, this.data.time.tm_ms));
        return date;
      }
    }

    /**
     * The Gyroscope class reports rotational data from the Phidget containing a gyroscope chip for use in your code. Phidget gyroscopes usually have multiple sensors, each oriented in a different axis, so multiple dimensions of heading can be recorded.
     *
     * If the Phidget you're using also has an accelerometer and a magnetometer, you may want to use the Spatial classin order to get all of the data at the same time, in a single event.
     * @public
     */
    class GyroscopeBase extends PhidgetChannel {
      /** @internal */
      data;
      onAngularRateUpdate = null;
      /** @internal */
      _gotAngularRateUpdateErrorEvent;
      constructor(ch) {
        super(ch);
        this._class = exports.ChannelClass.GYROSCOPE;
        this.name = "Gyroscope";
        this.data = this._initData();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 54:
            if (bp.entryCount > 1) this.data.dataInterval = bp.entries[1].v;else this.data.dataInterval = bp.entries[0].v;
            this._FIREPropertyChange('DataInterval', bp);
            this._FIREPropertyChange('DataRate', bp);
            break;
          case 170:
            this.data.heatingEnabled = bp.entries[0].v;
            this._FIREPropertyChange('HeatingEnabled', bp);
            break;
          case 145:
            this.data.precision = bp.entries[0].v;
            this._FIREPropertyChange('Precision', bp);
            break;
          case 106:
            break;
          case 2:
            {
              this.data.angularRate = bp.entries[0].v;
              this.data.timestamp = bp.entries[1].v;
              if (this._isAttachedDone && this.onAngularRateUpdate) {
                try {
                  this.onAngularRateUpdate(this.data.angularRate, this.data.timestamp);
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          default:
            throw new PhidgetError(exports.ErrorCode.INVALID_PACKET, "Unsupported bridge packet: 0x" + bp.vpkt.toString(16));
        }
      }
      /** @internal */
      _initData() {
        return {
          dataInterval: 1e+300,
          maxDataInterval: 4294967295,
          minDataRate: 1e+300,
          maxDataRate: 1e+300,
          maxAngularRate: [1e+300, 1e+300, 1e+300],
          minDataInterval: 4294967295,
          minAngularRate: [1e+300, 1e+300, 1e+300],
          angularRate: [1e+300, 1e+300, 1e+300],
          axisCount: 2147483647,
          timestamp: 1e+300,
          precision: 2147483647,
          heatingEnabled: 2
        };
      }
      /** @internal */
      _initAfterOpen() {}
      /** @internal */
      async _setDefaults() {}
      /** @internal */
      _hasInitialState() {
        return true;
      }
      /** @internal */
      _fireInitialEvents() {}
      /**
       * The most recent angular rate value that the channel has reported.
       *
       * *   This value will always be between `minAngularRate` and `maxAngularRate`.
       * @throws `PhidgetError`
       */
      get angularRate() {
        return this.getAngularRate();
      }
      /**
       * The minimum value the `AngularRateUpdate` event will report.
       * @throws `PhidgetError`
       */
      get minAngularRate() {
        return this.getMinAngularRate();
      }
      /**
       * The maximum value the `AngularRateUpdate` event will report.
       * @throws `PhidgetError`
       */
      get maxAngularRate() {
        return this.getMaxAngularRate();
      }
      /**
       * The number of axes the channel can measure angular rate on.
       *
       * *   See your device's User Guide for more information about the number of axes and their orientation.
       * @throws `PhidgetError`
       */
      get axisCount() {
        return this.getAxisCount();
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `AngularRateUpdate` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * @throws `PhidgetError`
       */
      get dataInterval() {
        return this.getDataInterval();
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get minDataInterval() {
        return this.getMinDataInterval();
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataInterval() {
        return this.getMaxDataInterval();
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       */
      get dataRate() {
        return this.getDataRate();
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get minDataRate() {
        return this.getMinDataRate();
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataRate() {
        return this.getMaxDataRate();
      }
      /**
       * Set to TRUE to enable the temperature stabilization feature of this device. This enables onboard heating elements to bring the board up to a known temperature to minimize ambient temerature effects on the sensor's reading. You can leave this setting FALSE to conserve power consumption.
       *
       * If you enable heating, it is strongly recommended to keep the board in its enclosure to keep it insulated from moving air.
       *
       * This property is shared by any and all spatial-related objects on this device (Accelerometer, Gyroscope, Magnetometer, Spatial)
       * @throws `PhidgetError`
       */
      get heatingEnabled() {
        return this.getHeatingEnabled();
      }
      /**
       * Selects between high/low precision sensing chips.
       * @throws `PhidgetError`
       * @internal
       */
      get precision() {
        return this.getPrecision();
      }
      /**
       * The most recent timestamp value that the channel has reported. This is an extremely accurate time measurement streamed from the device.
       *
       * *   If your application requires a time measurement, you should use this value over a local software timestamp.
       * @throws `PhidgetError`
       */
      get timestamp() {
        return this.getTimestamp();
      }
      /**
       * The most recent angular rate value that the channel has reported.
       *
       * *   This value will always be between `minAngularRate` and `maxAngularRate`.
       * @returns The last reported angular rate
       * @throws `PhidgetError`
       */
      getAngularRate() {
        var _context;
        this._assertOpen();
        if (_includesInstanceProperty(_context = this.data.angularRate).call(_context, 1e+300)) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.angularRate;
      }
      /**
       * The minimum value the `AngularRateUpdate` event will report.
       * @returns The angular rate values
       * @throws `PhidgetError`
       */
      getMinAngularRate() {
        var _context2;
        this._assertOpen();
        if (_includesInstanceProperty(_context2 = this.data.minAngularRate).call(_context2, 1e+300)) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minAngularRate;
      }
      /**
       * The maximum value the `AngularRateUpdate` event will report.
       * @returns The angular rate values
       * @throws `PhidgetError`
       */
      getMaxAngularRate() {
        var _context3;
        this._assertOpen();
        if (_includesInstanceProperty(_context3 = this.data.maxAngularRate).call(_context3, 1e+300)) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxAngularRate;
      }
      /**
       * The number of axes the channel can measure angular rate on.
       *
       * *   See your device's User Guide for more information about the number of axes and their orientation.
       * @returns Axis count value
       * @throws `PhidgetError`
       */
      getAxisCount() {
        this._assertOpen();
        if (this.data.axisCount === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.axisCount;
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `AngularRateUpdate` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getDataInterval() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.dataInterval;
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `AngularRateUpdate` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * @throws `PhidgetError`
       * @param dataInterval - The data interval value
       */
      async setDataInterval(dataInterval) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: dataInterval
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMinDataInterval() {
        this._assertOpen();
        if (this.data.minDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataInterval;
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMaxDataInterval() {
        this._assertOpen();
        if (this.data.maxDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @returns The data rate for the channel
       * @throws `PhidgetError`
       */
      getDataRate() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return 1000.0 / this.data.dataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       * @param dataRate - The data rate for the channel
       */
      async setDataRate(dataRate) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: Math.round(1000.0 / dataRate)
        });
        bp.set({
          name: "1",
          type: "g",
          value: 1000.0 / dataRate
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMinDataRate() {
        this._assertOpen();
        if (this.data.minDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataRate;
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMaxDataRate() {
        this._assertOpen();
        if (this.data.maxDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataRate;
      }
      /**
       * Set to TRUE to enable the temperature stabilization feature of this device. This enables onboard heating elements to bring the board up to a known temperature to minimize ambient temerature effects on the sensor's reading. You can leave this setting FALSE to conserve power consumption.
       *
       * If you enable heating, it is strongly recommended to keep the board in its enclosure to keep it insulated from moving air.
       *
       * This property is shared by any and all spatial-related objects on this device (Accelerometer, Gyroscope, Magnetometer, Spatial)
       * @returns Whether self-heating temperature stabilization is enabled
       * @throws `PhidgetError`
       */
      getHeatingEnabled() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 353:
          case 358:
          case 363:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.heatingEnabled === 2) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return !!this.data.heatingEnabled;
      }
      /**
       * Set to TRUE to enable the temperature stabilization feature of this device. This enables onboard heating elements to bring the board up to a known temperature to minimize ambient temerature effects on the sensor's reading. You can leave this setting FALSE to conserve power consumption.
       *
       * If you enable heating, it is strongly recommended to keep the board in its enclosure to keep it insulated from moving air.
       *
       * This property is shared by any and all spatial-related objects on this device (Accelerometer, Gyroscope, Magnetometer, Spatial)
       * @throws `PhidgetError`
       * @param heatingEnabled - Whether self-heating temperature stabilization is enabled
       */
      async setHeatingEnabled(heatingEnabled) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: heatingEnabled ? 1 : 0
        });
        await bp.send(this._ch, 170);
      }
      /**
       * Selects between high/low precision sensing chips.
       * @returns The sensor precision value
       * @throws `PhidgetError`
       * @internal
       */
      getPrecision() {
        this._assertOpen();
        if (this.data.precision === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.precision;
      }
      /**
       * Selects between high/low precision sensing chips.
       * @throws `PhidgetError`
       * @param precision - The sensor precision value
       * @internal
       */
      async setPrecision(precision) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: precision
        });
        await bp.send(this._ch, 145);
      }
      /**
       * The most recent timestamp value that the channel has reported. This is an extremely accurate time measurement streamed from the device.
       *
       * *   If your application requires a time measurement, you should use this value over a local software timestamp.
       * @returns The timestamp value
       * @throws `PhidgetError`
       */
      getTimestamp() {
        this._assertOpen();
        if (this.data.timestamp === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.timestamp;
      }
      /**
       * Re-zeros the gyroscope in 1-2 seconds.
       *
       * *   The device must be stationary when zeroing.
       * *   The angular rate will be reported as 0.0°/s while zeroing.
       * *   Zeroing the gyroscope is a method of compensating for the drift that is inherent to all gyroscopes. See your device's User Guide for more information on dealing with drift.
       * @throws `PhidgetError`
       */
      async zero() {
        this._assertOpen();
        const bp = new BridgePacket();
        await bp.send(this._ch, 106);
      }
    }

    /** @public */
    class Gyroscope extends GyroscopeBase {
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 10:
            if (bp.entryCount > 1) this.data.dataInterval = bp.getNumber(1);else this.data.dataInterval = bp.getNumber(0);
            this._FIREPropertyChange('DataInterval');
            this._FIREPropertyChange('DataRate');
            break;
          case 179:
            this.data.heatingEnabled = bp.entries[0].v;
            this._FIREPropertyChange('HeatingEnabled', bp);
            break;
          default:
            super._bridgeInput(bp);
            break;
        }
      }
      /** @internal */
      _errorHandler(code) {
        switch (code) {
          case exports.ErrorEventCode.SATURATION:
            this.data.angularRate = [1e+300, 1e+300, 1e+300];
            this.data.timestamp = 1e+300;
            this._gotAngularRateUpdateErrorEvent = true;
            break;
        }
      }
    }

    /**
     * The hub class allows you to control power to VINT hub ports.
     * @public
     */
    class HubBase extends PhidgetChannel {
      /** @internal */
      data;
      constructor(ch) {
        super(ch);
        this._class = exports.ChannelClass.HUB;
        this.name = "Hub";
        this.data = this._initData();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 60:
            break;
          case 183:
            break;
          case 72:
            break;
          case 73:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.INVALID_PACKET, "Unsupported bridge packet: 0x" + bp.vpkt.toString(16));
        }
      }
      /** @internal */
      _initData() {
        return {};
      }
      /** @internal */
      _initAfterOpen() {}
      /** @internal */
      async _setDefaults() {}
      /** @internal */
      _hasInitialState() {
        return true;
      }
      /** @internal */
      _fireInitialEvents() {}
      /**
       * Sets a flag on this hub port which forces the next VINT devices plugged in to stay in firmware upgrade mode.
       * @throws `PhidgetError`
       * @param port - The port the device is plugged into
       * @param timeout - The time to leave the flag set for
       * @internal
       */
      async setFirmwareUpgradeFlag(port, timeout) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: port
        });
        bp.set({
          name: "1",
          type: "u",
          value: timeout
        });
        await bp.send(this._ch, 60);
      }
      /**
       * Enables / disables Auto Set Speed on the hub port. When enabled, and a supported VINT device is attached, the **HubPortSpeed** will automatically be set to the fastest reliable speed. This is enabled by default on supported VINT Hubs.
       * @throws `PhidgetError`
       * @param port - The Hub port
       * @param state - The AutoSetSpeed state
       */
      async setPortAutoSetSpeed(port, state) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: port
        });
        bp.set({
          name: "1",
          type: "d",
          value: state ? 1 : 0
        });
        await bp.send(this._ch, 183);
      }
      /**
       * Sets the mode of the selected port. This could be used to set a port back to VINT mode if it was left in digital/analog mode.
       * @throws `PhidgetError`
       * @param port - The port being set
       * @param mode - The mode the port is being set to
       */
      async setPortMode(port, mode) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: port
        });
        bp.set({
          name: "1",
          type: "d",
          value: mode
        });
        await bp.send(this._ch, 72);
      }
      /**
       * Controls power to the VINT Hub Port.
       * @throws `PhidgetError`
       * @param port - The Hub port
       * @param state - The power state
       */
      async setPortPower(port, state) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: port
        });
        bp.set({
          name: "1",
          type: "d",
          value: state ? 1 : 0
        });
        await bp.send(this._ch, 73);
      }
    }

    /** @public */
    class Hub extends HubBase {
      async getPortMode(port) {
        this._assertAttached();
        if (!this._ch.conn._isLocal) throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        if (port < 0 || port > this.hubPortCount - 1) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Value must be in range: 0 - " + (this.hubPortCount - 1) + ".");
        await this.hub._device.openAndUpdatePortProperties(port);
        const mode = this.hub._device.hubPortProps?.[port].portMode;
        if (mode == undefined) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return mode;
      }
      async getPortPower(port) {
        this._assertAttached();
        if (!this._ch.conn._isLocal) throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        if (port < 0 || port > this.hubPortCount - 1) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Value must be in range: 0 - " + (this.hubPortCount - 1) + ".");
        await this.hub._device.openAndUpdatePortProperties(port);
        const power = this.hub._device.hubPortProps?.[port].portPowered;
        if (power == undefined) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return power;
      }
      getPortMaxSpeed(port) {
        this._assertAttached();
        if (!this._ch.conn._isLocal) throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        if (port < 0 || port > this.hubPortCount - 1) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Value must be in range: 0 - " + (this.hubPortCount - 1) + ".");
        const portMaxSpeed = this.hub._device.hubPortProps?.[port].portMaxSpeed;
        if (portMaxSpeed == undefined) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return portMaxSpeed;
      }
      getPortSupportsAutoSetSpeed(port) {
        this._assertAttached();
        if (!this._ch.conn._isLocal) throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        if (port < 0 || port > this.hubPortCount - 1) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Value must be in range: 0 - " + (this.hubPortCount - 1) + ".");
        const portSuppAutoSetSpeed = this.hub._device.hubPortProps?.[port].portSuppAutoSetSpeed;
        if (portSuppAutoSetSpeed == undefined) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return portSuppAutoSetSpeed;
      }
      getPortSupportsSetSpeed(port) {
        this._assertAttached();
        if (!this._ch.conn._isLocal) throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        if (port < 0 || port > this.hubPortCount - 1) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Value must be in range: 0 - " + (this.hubPortCount - 1) + ".");
        const portSuppSetSpeed = this.hub._device.hubPortProps?.[port].portSuppSetSpeed;
        if (portSuppSetSpeed == undefined) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return portSuppSetSpeed;
      }
      async setFirmwareUpgradeFlag(port, timeout) {
        this._assertAttached();
        if (port < 0 || port > this.hubPortCount - 1) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Value must be in range: 0 - " + (this.hubPortCount - 1) + ".");
        await super.setFirmwareUpgradeFlag(port, timeout);
      }
      async setPortMode(port, mode) {
        this._assertAttached();
        if (port < 0 || port > this.hubPortCount - 1) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Value must be in range: 0 - " + (this.hubPortCount - 1) + ".");
        await super.setPortMode(port, mode);
      }
      async setPortPower(port, state) {
        this._assertAttached();
        if (port < 0 || port > this.hubPortCount - 1) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Value must be in range: 0 - " + (this.hubPortCount - 1) + ".");
        await super.setPortPower(port, state);
      }
      async setPortAutoSetSpeed(port, state) {
        this._assertAttached();
        if (port < 0 || port > this.hubPortCount - 1) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Value must be in range: 0 - " + (this.hubPortCount - 1) + ".");
        await super.setPortAutoSetSpeed(port, state);
      }
    }

    /**
     * The Humidity Sensor class gathers relative humidity data from the Phidget and makes it available to your code.
     *
     * If you're using a simple 0-5V sensor that does not have its own firmware, use the VoltageInput or VoltageRatioInput class instead, as specified for your device.
     * @public
     */
    class HumiditySensorBase extends PhidgetChannel {
      /** @internal */
      data;
      onHumidityChange = null;
      /** @internal */
      _gotHumidityChangeErrorEvent;
      constructor(ch) {
        super(ch);
        this._class = exports.ChannelClass.HUMIDITY_SENSOR;
        this.name = "HumiditySensor";
        this.data = this._initData();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 54:
            if (bp.entryCount > 1) this.data.dataInterval = bp.entries[1].v;else this.data.dataInterval = bp.entries[0].v;
            this._FIREPropertyChange('DataInterval', bp);
            this._FIREPropertyChange('DataRate', bp);
            break;
          case 46:
            this.data.humidityChangeTrigger = bp.entries[0].v;
            this._FIREPropertyChange('HumidityChangeTrigger', bp);
            break;
          case 22:
            {
              this.data.humidity = bp.entries[0].v;
              if (this._isAttachedDone && this.onHumidityChange) {
                try {
                  this.onHumidityChange(this.data.humidity);
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          default:
            throw new PhidgetError(exports.ErrorCode.INVALID_PACKET, "Unsupported bridge packet: 0x" + bp.vpkt.toString(16));
        }
      }
      /** @internal */
      _initData() {
        return {
          dataInterval: 1e+300,
          maxDataInterval: 4294967295,
          minDataRate: 1e+300,
          maxDataRate: 1e+300,
          maxHumidity: 1e+300,
          maxHumidityChangeTrigger: 1e+300,
          minDataInterval: 4294967295,
          minHumidity: 1e+300,
          minHumidityChangeTrigger: 1e+300,
          humidity: 1e+300,
          humidityChangeTrigger: 1e+300
        };
      }
      /** @internal */
      _initAfterOpen() {}
      /** @internal */
      async _setDefaults() {}
      /** @internal */
      _hasInitialState() {
        return true;
      }
      /** @internal */
      _fireInitialEvents() {}
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `HumidityChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between `HumidityChange` events can also be affected by the `humidityChangeTrigger`.
       * @throws `PhidgetError`
       */
      get dataInterval() {
        return this.getDataInterval();
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get minDataInterval() {
        return this.getMinDataInterval();
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataInterval() {
        return this.getMaxDataInterval();
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       */
      get dataRate() {
        return this.getDataRate();
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get minDataRate() {
        return this.getMinDataRate();
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataRate() {
        return this.getMaxDataRate();
      }
      /**
       * The most recent humidity value that the channel has reported.
       *
       * *   This value will always be between `minHumidity` and `maxHumidity`.
       * @throws `PhidgetError`
       */
      get humidity() {
        return this.getHumidity();
      }
      /**
       * The minimum value that the `HumidityChange` event will report.
       * @throws `PhidgetError`
       */
      get minHumidity() {
        return this.getMinHumidity();
      }
      /**
       * The maximum value that the `HumidityChange` event will report.
       * @throws `PhidgetError`
       */
      get maxHumidity() {
        return this.getMaxHumidity();
      }
      /**
       * The channel will not issue a `HumidityChange` event until the humidity value has changed by the amount specified by the `humidityChangeTrigger`.
       *
       * *   Setting the `humidityChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering.
       * @throws `PhidgetError`
       */
      get humidityChangeTrigger() {
        return this.getHumidityChangeTrigger();
      }
      /**
       * The minimum value that `humidityChangeTrigger` can be set to.
       * @throws `PhidgetError`
       */
      get minHumidityChangeTrigger() {
        return this.getMinHumidityChangeTrigger();
      }
      /**
       * The maximum value that `humidityChangeTrigger` can be set to.
       * @throws `PhidgetError`
       */
      get maxHumidityChangeTrigger() {
        return this.getMaxHumidityChangeTrigger();
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `HumidityChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between `HumidityChange` events can also be affected by the `humidityChangeTrigger`.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getDataInterval() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.dataInterval;
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `HumidityChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between `HumidityChange` events can also be affected by the `humidityChangeTrigger`.
       * @throws `PhidgetError`
       * @param dataInterval - The data interval value
       */
      async setDataInterval(dataInterval) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: dataInterval
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMinDataInterval() {
        this._assertOpen();
        if (this.data.minDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataInterval;
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMaxDataInterval() {
        this._assertOpen();
        if (this.data.maxDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @returns The data rate for the channel
       * @throws `PhidgetError`
       */
      getDataRate() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return 1000.0 / this.data.dataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       * @param dataRate - The data rate for the channel
       */
      async setDataRate(dataRate) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: Math.round(1000.0 / dataRate)
        });
        bp.set({
          name: "1",
          type: "g",
          value: 1000.0 / dataRate
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMinDataRate() {
        this._assertOpen();
        if (this.data.minDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataRate;
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMaxDataRate() {
        this._assertOpen();
        if (this.data.maxDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataRate;
      }
      /**
       * The most recent humidity value that the channel has reported.
       *
       * *   This value will always be between `minHumidity` and `maxHumidity`.
       * @returns The humidity value
       * @throws `PhidgetError`
       */
      getHumidity() {
        this._assertOpen();
        if (this.data.humidity === 1e+300 || Number.isNaN(this.data.humidity)) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        if (this.data.humidity > this.data.maxHumidity) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE_HIGH);
        if (this.data.humidity < this.data.minHumidity) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE_LOW);
        return this.data.humidity;
      }
      /**
       * The minimum value that the `HumidityChange` event will report.
       * @returns The humidity value
       * @throws `PhidgetError`
       */
      getMinHumidity() {
        this._assertOpen();
        if (this.data.minHumidity === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minHumidity;
      }
      /**
       * The maximum value that the `HumidityChange` event will report.
       * @returns The humidity value
       * @throws `PhidgetError`
       */
      getMaxHumidity() {
        this._assertOpen();
        if (this.data.maxHumidity === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxHumidity;
      }
      /**
       * The channel will not issue a `HumidityChange` event until the humidity value has changed by the amount specified by the `humidityChangeTrigger`.
       *
       * *   Setting the `humidityChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering.
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getHumidityChangeTrigger() {
        this._assertOpen();
        if (this.data.humidityChangeTrigger === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.humidityChangeTrigger;
      }
      /**
       * The channel will not issue a `HumidityChange` event until the humidity value has changed by the amount specified by the `humidityChangeTrigger`.
       *
       * *   Setting the `humidityChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering.
       * @throws `PhidgetError`
       * @param humidityChangeTrigger - The change trigger value
       */
      async setHumidityChangeTrigger(humidityChangeTrigger) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: humidityChangeTrigger
        });
        await bp.send(this._ch, 46);
      }
      /**
       * The minimum value that `humidityChangeTrigger` can be set to.
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getMinHumidityChangeTrigger() {
        this._assertOpen();
        if (this.data.minHumidityChangeTrigger === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minHumidityChangeTrigger;
      }
      /**
       * The maximum value that `humidityChangeTrigger` can be set to.
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getMaxHumidityChangeTrigger() {
        this._assertOpen();
        if (this.data.maxHumidityChangeTrigger === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxHumidityChangeTrigger;
      }
    }

    /** @public */
    class HumiditySensor extends HumiditySensorBase {
      /** @internal */
      _errorHandler(code) {
        switch (code) {
          case exports.ErrorEventCode.SATURATION:
            this.data.humidity = 1e+300;
            this._gotHumidityChangeErrorEvent = true;
            break;
        }
      }
    }

    /**
     * The Infrared Remote class lets you read and transmit command codes from infrared remotes that the majority of household appliances use. You can use this class to construct and transmit commands from scratch, or learn and retransmit codes from the remote controller of your appliance.
     * @public
     */
    class IRBase extends PhidgetChannel {
      /** @internal */
      data;
      onCode = null;
      /** @internal */
      _gotCodeErrorEvent;
      onLearn = null;
      /** @internal */
      _gotLearnErrorEvent;
      onRawData = null;
      /** @internal */
      _gotRawDataErrorEvent;
      constructor(ch) {
        super(ch);
        this._class = exports.ChannelClass.IR;
        this.name = "IR";
        this.data = this._initData();
      }
      static get RAW_DATA_LONG_SPACE() {
        return 4294967295;
      }
      static get MAX_CODE_BIT_COUNT() {
        return 128;
      }
      static get MAX_CODE_STRING_LENGTH() {
        return 33;
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 97:
            break;
          case 98:
            break;
          case 99:
            break;
          case 32:
            {
              if (this._isAttachedDone && this.onRawData) {
                try {
                  this.onRawData(bp.entries[0].v);
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          default:
            throw new PhidgetError(exports.ErrorCode.INVALID_PACKET, "Unsupported bridge packet: 0x" + bp.vpkt.toString(16));
        }
      }
      /** @internal */
      _initData() {
        return {
          lastCodeInfo: null,
          lastLearnedCodeInfo: null,
          lastCodeStr: null,
          lastCodeBitCount: 0,
          lastLearnedCodeStr: null
        };
      }
      /** @internal */
      _initAfterOpen() {}
      /** @internal */
      async _setDefaults() {}
      /** @internal */
      _hasInitialState() {
        return true;
      }
      /** @internal */
      _fireInitialEvents() {}
      /**
       * Transmits a repeat of the last transmited code.
       *
       * *   Depending on the CodeInfo structure, this may be a retransmission of the code itself, or there may be a special repeat code.
       * @throws `PhidgetError`
       */
      async transmitRepeat() {
        this._assertOpen();
        const bp = new BridgePacket();
        await bp.send(this._ch, 99);
      }
    }

    /** @public */
    class IR extends IRBase {
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 33:
            if (this._isAttachedDone && this.onCode) {
              try {
                this.onCode(this.data.lastCodeStr, this.data.lastCodeBitCount, true);
              } catch (err) {
                logEventException(err);
              }
            }
            break;
          case 5:
            this.data.lastCodeStr = bp.getString(0);
            this.data.lastCodeBitCount = bp.getNumber(1);
            if (this._isAttachedDone && this.onCode) {
              try {
                this.onCode(this.data.lastCodeStr, this.data.lastCodeBitCount, bp.getBoolean(2));
              } catch (err) {
                logEventException(err);
              }
            }
            break;
          case 25:
            {
              const toggleString = String.fromCharCode(...bp.getArray("CodeInfo.toggleMask")).replace(/\u0000/g, '');
              const repeatArr = bp.getArray("CodeInfo.repeat");
              while (repeatArr[repeatArr.length - 1] === 0) repeatArr.pop();
              this.data.lastLearnedCodeStr = bp.getString("0");
              this.data.lastLearnedCodeInfo = {
                bitCount: bp.getNumber("CodeInfo.bitCount"),
                encoding: bp.getNumber("CodeInfo.encoding"),
                length: bp.getNumber("CodeInfo.length"),
                gap: bp.getNumber("CodeInfo.gap"),
                trail: bp.getNumber("CodeInfo.trail"),
                header: bp.getArray("CodeInfo.header"),
                one: bp.getArray("CodeInfo.one"),
                zero: bp.getArray("CodeInfo.zero"),
                repeat: repeatArr,
                minRepeat: bp.getNumber("CodeInfo.minRepeat"),
                dutyCycle: bp.getNumber("CodeInfo.dutyCycle"),
                carrierFrequency: bp.getNumber("CodeInfo.carrierFrequency"),
                toggleMask: toggleString
              };
              if (this._isAttachedDone && this.onLearn) {
                try {
                  this.onLearn(this.data.lastLearnedCodeStr, this.data.lastLearnedCodeInfo);
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          default:
            super._bridgeInput(bp);
            break;
        }
      }
      async transmit(code, ci) {
        this._assertOpen();
        const codeInfo = {
          bitCount: 0,
          encoding: exports.IRCodeEncoding.SPACE,
          length: exports.IRCodeLength.CONSTANT,
          gap: 0,
          trail: 0,
          minRepeat: 0,
          dutyCycle: 0,
          carrierFrequency: 0,
          header: [0, 0],
          one: [0, 0],
          zero: [0, 0]};
        if (ci.bitCount !== undefined) codeInfo.bitCount = ci.bitCount;
        if (ci.encoding !== undefined) codeInfo.encoding = ci.encoding;
        if (ci.length !== undefined) codeInfo.length = ci.length;
        if (ci.gap !== undefined) codeInfo.gap = ci.gap;
        if (ci.trail !== undefined) codeInfo.trail = ci.trail;
        if (ci.minRepeat !== undefined) codeInfo.minRepeat = ci.minRepeat;
        if (ci.dutyCycle !== undefined) codeInfo.dutyCycle = ci.dutyCycle;
        if (ci.carrierFrequency !== undefined) codeInfo.carrierFrequency = ci.carrierFrequency;
        if (ci.header !== undefined) {
          if (!Array.isArray(ci.header)) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, 'invalid value - header must be Array');
          if (ci.header.length != 2) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, 'invalid value - header must have length 2');
          codeInfo.header = ci.header;
        }
        if (ci.one !== undefined) {
          if (!Array.isArray(ci.one)) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, 'invalid value - one must be Array');
          if (ci.one.length != 2) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, 'invalid value - one must have length 2');
          codeInfo.one = ci.one;
        }
        if (ci.zero !== undefined) {
          if (!Array.isArray(ci.zero)) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, 'invalid value - zero must be Array');
          if (ci.zero.length != 2) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, 'invalid value - zero must have length 2');
          codeInfo.zero = ci.zero;
        }
        const repeatArr = new Array(26).fill(0);
        if (ci.repeat !== undefined) {
          if (!Array.isArray(ci.repeat)) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, 'invalid value - repeat must be Array');
          if (ci.repeat.length > 26) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, 'invalid value - repeat must have length <= 26');
          for (let i = 0; i < ci.repeat.length; i++) repeatArr[i] = ci.repeat[i];
        }
        const toggleMaskArr = new Array(33).fill(0);
        if (ci.toggleMask !== undefined) {
          if (typeof ci.toggleMask !== 'string') throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, 'invalid value - toggleMask must be a string');
          if (ci.toggleMask.length > 33) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, 'invalid value - toggleMask must have length <= 33');
          for (let i = 0; i < ci.toggleMask.length; i++) toggleMaskArr[i] = ci.toggleMask.charCodeAt(i);
        }
        const bp = new BridgePacket();
        bp.set({
          name: 'code',
          type: 's',
          value: code
        });
        bp.set({
          name: 'CodeInfo.bitCount',
          type: 'u',
          value: codeInfo.bitCount
        });
        bp.set({
          name: 'CodeInfo.encoding',
          type: 'd',
          value: codeInfo.encoding
        });
        bp.set({
          name: 'CodeInfo.length',
          type: 'd',
          value: codeInfo.length
        });
        bp.set({
          name: 'CodeInfo.gap',
          type: 'u',
          value: codeInfo.gap
        });
        bp.set({
          name: 'CodeInfo.trail',
          type: 'u',
          value: codeInfo.trail
        });
        bp.set({
          name: 'CodeInfo.header',
          type: 'U',
          value: codeInfo.header
        });
        bp.set({
          name: 'CodeInfo.one',
          type: 'U',
          value: codeInfo.one
        });
        bp.set({
          name: 'CodeInfo.zero',
          type: 'U',
          value: codeInfo.zero
        });
        bp.set({
          name: 'CodeInfo.repeat',
          type: 'U',
          value: repeatArr
        });
        bp.set({
          name: 'CodeInfo.minRepeat',
          type: 'u',
          value: codeInfo.minRepeat
        });
        bp.set({
          name: 'CodeInfo.dutyCycle',
          type: 'g',
          value: codeInfo.dutyCycle
        });
        bp.set({
          name: 'CodeInfo.carrierFrequency',
          type: 'u',
          value: codeInfo.carrierFrequency
        });
        bp.set({
          name: 'CodeInfo.toggleMask',
          type: 'R',
          value: new Uint8Array(toggleMaskArr)
        });
        await bp.send(this._ch, 97);
      }
      async transmitRaw(data, carrierFrequency = 0, dutyCycle = 0, gap = 0) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: 'data',
          type: 'U',
          value: data
        });
        bp.set({
          name: 'carrierFrequency',
          type: 'u',
          value: carrierFrequency
        });
        bp.set({
          name: 'dutyCycle',
          type: 'g',
          value: dutyCycle
        });
        bp.set({
          name: 'gap',
          type: 'u',
          value: gap
        });
        await bp.send(this._ch, 98);
      }
      getLastCode() {
        this._assertOpen();
        if (this.data.lastCodeStr == undefined) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return {
          code: this.data.lastCodeStr,
          bitCount: this.data.lastCodeBitCount
        };
      }
      getLastLearnedCode() {
        this._assertOpen();
        if (this.data.lastLearnedCodeStr == undefined || this.data.lastLearnedCodeInfo == undefined) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return {
          code: this.data.lastLearnedCodeStr,
          codeInfo: this.data.lastLearnedCodeInfo
        };
      }
    }

    /**
     * The LCD class allows you to control various liquid crystal displays. It offers control of displayed text as well as screen settings and custom character creation.
     * @public
     */
    class LCDBase extends PhidgetChannel {
      /** @internal */
      data;
      constructor(ch) {
        super(ch);
        this._class = exports.ChannelClass.LCD;
        this.name = "LCD";
        this.data = this._initData();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 43:
            this.data.backlight = bp.entries[0].v;
            this._FIREPropertyChange('Backlight', bp);
            break;
          case 47:
            break;
          case 4:
            break;
          case 48:
            this.data.contrast = bp.entries[0].v;
            this._FIREPropertyChange('Contrast', bp);
            break;
          case 6:
            break;
          case 52:
            this.data.cursorBlink = bp.entries[0].v;
            this._FIREPropertyChange('CursorBlink', bp);
            break;
          case 53:
            this.data.cursorOn = bp.entries[0].v;
            this._FIREPropertyChange('CursorOn', bp);
            break;
          case 13:
            break;
          case 14:
            break;
          case 15:
            break;
          case 19:
            break;
          case 62:
            this.data.frameBuffer = bp.entries[0].v;
            this._FIREPropertyChange('FrameBuffer', bp);
            break;
          case 24:
            break;
          case 38:
            break;
          case 78:
            this.data.screenSize = bp.entries[0].v;
            this._FIREPropertyChange('ScreenSize', bp);
            break;
          case 80:
            this.data.sleeping = bp.entries[0].v;
            this._FIREPropertyChange('Sleeping', bp);
            break;
          case 104:
            break;
          case 105:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.INVALID_PACKET, "Unsupported bridge packet: 0x" + bp.vpkt.toString(16));
        }
      }
      /** @internal */
      _initData() {
        return {
          fontWidth: [255, 255, 255],
          fontHeight: [255, 255, 255],
          backlight: 1e+300,
          minBacklight: 1e+300,
          maxBacklight: 1e+300,
          contrast: 1e+300,
          minContrast: 1e+300,
          maxContrast: 1e+300,
          cursorBlink: 2,
          cursorOn: 2,
          frameBuffer: 2147483647,
          height: 2147483647,
          width: 2147483647,
          screenSize: 2147483647,
          sleeping: 2,
          autoFlush: 2
        };
      }
      /** @internal */
      _initAfterOpen() {}
      /** @internal */
      async _setDefaults() {}
      /** @internal */
      _hasInitialState() {
        return true;
      }
      /** @internal */
      _fireInitialEvents() {}
      /**
       * Set to true to automatically flush the LCD screen after every message that writes to the LCD.
       * @throws `PhidgetError`
       */
      get autoFlush() {
        return this.getAutoFlush();
      }
      set autoFlush(autoFlush) {
        this.setAutoFlush(autoFlush);
      }
      /**
       * The `backlight` affects the brightness of the LCD screen.
       *
       * *   `backlight` is bounded by `minBacklight` and `maxBacklight`.
       * @throws `PhidgetError`
       */
      get backlight() {
        return this.getBacklight();
      }
      /**
       * The minimum value that `backlight` can be set to.
       * @throws `PhidgetError`
       */
      get minBacklight() {
        return this.getMinBacklight();
      }
      /**
       * The maximum value that `backlight` can be set to.
       * @throws `PhidgetError`
       */
      get maxBacklight() {
        return this.getMaxBacklight();
      }
      /**
       * Contrast level of the text or graphic pixels.
       *
       * *   A higher contrast will make the image darker.
       * *   `contrast` is bounded by `minContrast` and `maxContrast`.
       * @throws `PhidgetError`
       */
      get contrast() {
        return this.getContrast();
      }
      /**
       * The minimum value that `contrast` can be set to.
       * @throws `PhidgetError`
       */
      get minContrast() {
        return this.getMinContrast();
      }
      /**
       * The maximum value that `contrast` can be set to.
       * @throws `PhidgetError`
       */
      get maxContrast() {
        return this.getMaxContrast();
      }
      /**
       * When `cursorBlink` is true, the device will cause the cursor to periodically blink.
       * @throws `PhidgetError`
       */
      get cursorBlink() {
        return this.getCursorBlink();
      }
      /**
       * When `cursorOn` is true, the device will underline to the cursor position.
       * @throws `PhidgetError`
       */
      get cursorOn() {
        return this.getCursorOn();
      }
      /**
       * The frame buffer that is currently being used.
       *
       * *   Commands sent to the device are performed on this buffer.
       * @throws `PhidgetError`
       */
      get frameBuffer() {
        return this.getFrameBuffer();
      }
      /**
       * The height of the LCD screen attached to the channel.
       * @throws `PhidgetError`
       */
      get height() {
        return this.getHeight();
      }
      /**
       * The size of the LCD screen attached to the channel.
       * @throws `PhidgetError`
       */
      get screenSize() {
        return this.getScreenSize();
      }
      /**
       * The on/off state of `sleeping`. Putting the device to sleep turns off the display and backlight in order to save power.
       *
       * *   The device will still take commands while asleep, and will wake up if the screen is flushed, or if the contrast or backlight are changed.
       * *   When the device wakes up, it will return to its last known state, taking into account any changes that happened while asleep.
       * @throws `PhidgetError`
       */
      get sleeping() {
        return this.getSleeping();
      }
      /**
       * The width of the LCD screen attached to the channel.
       * @throws `PhidgetError`
       */
      get width() {
        return this.getWidth();
      }
      /**
       * Set to true to automatically flush the LCD screen after every message that writes to the LCD.
       * @returns Allows setting the LCD to flush the screen automatically
       * @throws `PhidgetError`
       */
      getAutoFlush() {
        this._assertOpen();
        if (this.data.autoFlush === 2) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return !!this.data.autoFlush;
      }
      /**
       * The `backlight` affects the brightness of the LCD screen.
       *
       * *   `backlight` is bounded by `minBacklight` and `maxBacklight`.
       * @returns The backlight value
       * @throws `PhidgetError`
       */
      getBacklight() {
        this._assertOpen();
        if (this.data.backlight === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.backlight;
      }
      /**
       * The `backlight` affects the brightness of the LCD screen.
       *
       * *   `backlight` is bounded by `minBacklight` and `maxBacklight`.
       * @throws `PhidgetError`
       * @param backlight - The backlight value
       */
      async setBacklight(backlight) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: backlight
        });
        await bp.send(this._ch, 43);
      }
      /**
       * The minimum value that `backlight` can be set to.
       * @returns The backlight value
       * @throws `PhidgetError`
       */
      getMinBacklight() {
        this._assertOpen();
        if (this.data.minBacklight === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minBacklight;
      }
      /**
       * The maximum value that `backlight` can be set to.
       * @returns The backlight value
       * @throws `PhidgetError`
       */
      getMaxBacklight() {
        this._assertOpen();
        if (this.data.maxBacklight === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxBacklight;
      }
      /**
       * Clears all pixels in the current frame buffer.
       *
       * *   Changes made to the frame buffer must be flushed to the LCD screen using `flush()`.
       * @throws `PhidgetError`
       */
      async clear() {
        this._assertOpen();
        const bp = new BridgePacket();
        await bp.send(this._ch, 4);
      }
      /**
       * Contrast level of the text or graphic pixels.
       *
       * *   A higher contrast will make the image darker.
       * *   `contrast` is bounded by `minContrast` and `maxContrast`.
       * @returns The contrast value
       * @throws `PhidgetError`
       */
      getContrast() {
        this._assertOpen();
        if (this.data.contrast === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.contrast;
      }
      /**
       * Contrast level of the text or graphic pixels.
       *
       * *   A higher contrast will make the image darker.
       * *   `contrast` is bounded by `minContrast` and `maxContrast`.
       * @throws `PhidgetError`
       * @param contrast - The contrast value
       */
      async setContrast(contrast) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: contrast
        });
        await bp.send(this._ch, 48);
      }
      /**
       * The minimum value that `contrast` can be set to.
       * @returns The contrast value.
       * @throws `PhidgetError`
       */
      getMinContrast() {
        this._assertOpen();
        if (this.data.minContrast === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minContrast;
      }
      /**
       * The maximum value that `contrast` can be set to.
       * @returns The contrast value.
       * @throws `PhidgetError`
       */
      getMaxContrast() {
        this._assertOpen();
        if (this.data.maxContrast === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxContrast;
      }
      /**
       * Copies all pixels from a specified rectangular region to another.
       * @throws `PhidgetError`
       * @param sourceFramebuffer - Index number of the frame buffer containing the source rectangle
       * @param destFramebuffer - Index number of the frame buffer containing the destination rectangle
       * @param sourceX1 - X coordinate of upper left corner of source rectangle
       * @param sourceY1 - Y coordinate of upper left corner of source rectangle
       * @param sourceX2 - X coordinate of bottom right corner of source rectangle
       * @param sourceY2 - Y coordinate of bottom right corner of source rectangle
       * @param destX - X coordinate of upper left corner of destination rectangle
       * @param destY - Y coordinate of upper left corner of destination rectangle
       * @param inverted - If true, copied pixels are inverted
       */
      async copy(sourceFramebuffer, destFramebuffer, sourceX1, sourceY1, sourceX2, sourceY2, destX, destY, inverted) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: sourceFramebuffer
        });
        bp.set({
          name: "1",
          type: "d",
          value: destFramebuffer
        });
        bp.set({
          name: "2",
          type: "d",
          value: sourceX1
        });
        bp.set({
          name: "3",
          type: "d",
          value: sourceY1
        });
        bp.set({
          name: "4",
          type: "d",
          value: sourceX2
        });
        bp.set({
          name: "5",
          type: "d",
          value: sourceY2
        });
        bp.set({
          name: "6",
          type: "d",
          value: destX
        });
        bp.set({
          name: "7",
          type: "d",
          value: destY
        });
        bp.set({
          name: "8",
          type: "d",
          value: inverted ? 1 : 0
        });
        await bp.send(this._ch, 6);
      }
      /**
       * When `cursorBlink` is true, the device will cause the cursor to periodically blink.
       * @returns The cursor blink mode
       * @throws `PhidgetError`
       */
      getCursorBlink() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 343:
          case 342:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.cursorBlink === 2) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return !!this.data.cursorBlink;
      }
      /**
       * When `cursorBlink` is true, the device will cause the cursor to periodically blink.
       * @throws `PhidgetError`
       * @param cursorBlink - The cursor blink mode
       */
      async setCursorBlink(cursorBlink) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: cursorBlink ? 1 : 0
        });
        await bp.send(this._ch, 52);
      }
      /**
       * When `cursorOn` is true, the device will underline to the cursor position.
       * @returns The cursor on value
       * @throws `PhidgetError`
       */
      getCursorOn() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 343:
          case 342:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.cursorOn === 2) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return !!this.data.cursorOn;
      }
      /**
       * When `cursorOn` is true, the device will underline to the cursor position.
       * @throws `PhidgetError`
       * @param cursorOn - The cursor on value
       */
      async setCursorOn(cursorOn) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: cursorOn ? 1 : 0
        });
        await bp.send(this._ch, 53);
      }
      /**
       * Draws a straight line in the current frame buffer between two specified points
       *
       * *   Changes made to the frame buffer must be flushed to the LCD screen using `flush()`.
       * @throws `PhidgetError`
       * @param x1 - X coordinate of the first point
       * @param y1 - Y coordinate of the first point
       * @param x2 - X coordinate of the second point
       * @param y2 - Y coordinate of the second point
       */
      async drawLine(x1, y1, x2, y2) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: x1
        });
        bp.set({
          name: "1",
          type: "d",
          value: y1
        });
        bp.set({
          name: "2",
          type: "d",
          value: x2
        });
        bp.set({
          name: "3",
          type: "d",
          value: y2
        });
        await bp.send(this._ch, 13);
      }
      /**
       * Draws, erases, or inverts a single specified pixel.
       *
       * *   Changes made to the frame buffer must be flushed to the LCD screen using `flush()`.
       * @throws `PhidgetError`
       * @param x - The X coordinate of the pixel
       * @param y - The Y coordinate of the pixel
       * @param pixelState - The new state of the pixel.
       */
      async drawPixel(x, y, pixelState) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: x
        });
        bp.set({
          name: "1",
          type: "d",
          value: y
        });
        bp.set({
          name: "2",
          type: "d",
          value: pixelState
        });
        await bp.send(this._ch, 14);
      }
      /**
       * Draws a rectangle in the current frame buffer using the specified points
       *
       * *   Changes made to the frame buffer must be flushed to the LCD screen using `flush()`.
       * @throws `PhidgetError`
       * @param x1 - The X coordinate of the top-left corner of the rectangle
       * @param y1 - The Y coordinate of the top-left corner of the rectangle
       * @param x2 - The X coordinate of the bottom-right corner of the rectangle
       * @param y2 - The Y coordinate of the bottom-right corner of the rectangle
       * @param filled - If true, the rectangle will be solid. If false, just a single pixel outline.
       * @param inverted - If true, clears the region instead of drawing
       */
      async drawRect(x1, y1, x2, y2, filled, inverted) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: x1
        });
        bp.set({
          name: "1",
          type: "d",
          value: y1
        });
        bp.set({
          name: "2",
          type: "d",
          value: x2
        });
        bp.set({
          name: "3",
          type: "d",
          value: y2
        });
        bp.set({
          name: "4",
          type: "d",
          value: filled ? 1 : 0
        });
        bp.set({
          name: "5",
          type: "d",
          value: inverted ? 1 : 0
        });
        await bp.send(this._ch, 15);
      }
      /**
       * Flushes the buffered LCD contents to the LCD screen.
       * @throws `PhidgetError`
       */
      async flush() {
        this._assertOpen();
        const bp = new BridgePacket();
        await bp.send(this._ch, 19);
      }
      /**
       * Sets the size of the specified font.
       * @throws `PhidgetError`
       * @param font - The specified font
       * @param width - The width of the font
       * @param height - The height of the font
       */
      async setFontSize(font, width, height) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: font
        });
        bp.set({
          name: "1",
          type: "d",
          value: width
        });
        bp.set({
          name: "2",
          type: "d",
          value: height
        });
        await bp.send(this._ch, 61);
      }
      /**
       * The frame buffer that is currently being used.
       *
       * *   Commands sent to the device are performed on this buffer.
       * @returns The current frame buffer
       * @throws `PhidgetError`
       */
      getFrameBuffer() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 343:
          case 342:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.frameBuffer === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.frameBuffer;
      }
      /**
       * The frame buffer that is currently being used.
       *
       * *   Commands sent to the device are performed on this buffer.
       * @throws `PhidgetError`
       * @param frameBuffer - The current frame buffer
       */
      async setFrameBuffer(frameBuffer) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: frameBuffer
        });
        await bp.send(this._ch, 62);
      }
      /**
       * The height of the LCD screen attached to the channel.
       * @returns The height value
       * @throws `PhidgetError`
       */
      getHeight() {
        this._assertOpen();
        if (this.data.height === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.height;
      }
      /**
       * Initializes the Text LCD display
       * @throws `PhidgetError`
       */
      async initialize() {
        this._assertOpen();
        const bp = new BridgePacket();
        await bp.send(this._ch, 24);
      }
      /**
       * Writes the specified frame buffer to flash memory
       *
       * *   Use sparingly. The flash memory is only designed to be written to 10,000 times before it may become unusable. This method can only be called one time each time the channel is opened.
       * @throws `PhidgetError`
       * @param frameBuffer - The frame buffer to be saved
       */
      async saveFrameBuffer(frameBuffer) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: frameBuffer
        });
        await bp.send(this._ch, 38);
      }
      /**
       * The size of the LCD screen attached to the channel.
       * @returns The screen size
       * @throws `PhidgetError`
       */
      getScreenSize() {
        this._assertOpen();
        if (this.data.screenSize === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.screenSize;
      }
      /**
       * The size of the LCD screen attached to the channel.
       * @throws `PhidgetError`
       * @param screenSize - The screen size
       */
      async setScreenSize(screenSize) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: screenSize
        });
        await bp.send(this._ch, 78);
      }
      /**
       * The on/off state of `sleeping`. Putting the device to sleep turns off the display and backlight in order to save power.
       *
       * *   The device will still take commands while asleep, and will wake up if the screen is flushed, or if the contrast or backlight are changed.
       * *   When the device wakes up, it will return to its last known state, taking into account any changes that happened while asleep.
       * @returns The sleep status
       * @throws `PhidgetError`
       */
      getSleeping() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 343:
          case 342:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.sleeping === 2) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return !!this.data.sleeping;
      }
      /**
       * The on/off state of `sleeping`. Putting the device to sleep turns off the display and backlight in order to save power.
       *
       * *   The device will still take commands while asleep, and will wake up if the screen is flushed, or if the contrast or backlight are changed.
       * *   When the device wakes up, it will return to its last known state, taking into account any changes that happened while asleep.
       * @throws `PhidgetError`
       * @param sleeping - The sleep status
       */
      async setSleeping(sleeping) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: sleeping ? 1 : 0
        });
        await bp.send(this._ch, 80);
      }
      /**
       * The width of the LCD screen attached to the channel.
       * @returns The width value
       * @throws `PhidgetError`
       */
      getWidth() {
        this._assertOpen();
        if (this.data.width === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.width;
      }
      /**
       * Writes text to the current frame buffer at the specified location
       *
       * *   Changes made to the frame buffer must be flushed to the LCD screen using `flush()`.
       * @throws `PhidgetError`
       * @param font - The font of the text
       * @param xPosition - The X position of the start of the text string
       * @param yPosition - The Y position of the start of the text string
       * @param text - The text to be written
       */
      async writeText(font, xPosition, yPosition, text) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: font
        });
        bp.set({
          name: "1",
          type: "d",
          value: xPosition
        });
        bp.set({
          name: "2",
          type: "d",
          value: yPosition
        });
        bp.set({
          name: "3",
          type: "s",
          value: text
        });
        await bp.send(this._ch, 105);
      }
    }

    /** @public */
    class LCD extends LCDBase {
      /** @internal */
      _transactionLock;
      constructor(ch) {
        super(ch);
        this._transactionLock = new PhidgetLock();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 61:
            {
              const font = bp.getNumber(0);
              const width = bp.getNumber(1);
              const height = bp.getNumber(2);
              if (font < 1 || font > 2) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Font must be in range: 1 - 2.");
              if (height < 0 || height > this.data.height) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Height must be less than or equal to " + this.data.height);
              if (width < 0 || width > this.data.width) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Width must be less than or equal to " + this.data.width);
              this.data.fontWidth[font] = width;
              this.data.fontHeight[font] = height;
              this._FIREPropertyChange('FontSize', bp);
              break;
            }
          case 104:
            {
              const x = bp.getNumber(0);
              const y = bp.getNumber(1);
              const width = bp.getNumber(2);
              const height = bp.getNumber(3);
              if (x < 0 || x > this.data.width - 1) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "X must be less than or equal to " + (this.data.width - 1));
              if (y < 0 || y > this.data.height - 1) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Y must be less than or equal to " + (this.data.height - 1));
              if (width < 1 || width > this.data.width) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Width must be between 1 and " + this.data.width);
              if (height < 1 || height > this.data.height) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Height must be between 1 and " + this.data.height);
              super._bridgeInput(bp);
              break;
            }
          case 78:
            super._bridgeInput(bp);
            this._setWidthHeightFromScreenSize(bp.getNumber(0));
            break;
          case 43:
          case 48:
          case 19:
            super._bridgeInput(bp);
            switch (this._ch?.chDef.uid) {
              case 343:
              case 342:
                this.data.sleeping = 0;
                break;
            }
            break;
          default:
            super._bridgeInput(bp);
            break;
        }
      }
      /** @internal */
      _setWidthHeightFromScreenSize(size) {
        switch (size) {
          case exports.LCDScreenSize.NO_SCREEN:
            this.data.height = 0;
            this.data.width = 0;
            break;
          case exports.LCDScreenSize.DIMENSIONS_1X8:
            this.data.height = 1;
            this.data.width = 8;
            break;
          case exports.LCDScreenSize.DIMENSIONS_2X8:
            this.data.height = 2;
            this.data.width = 8;
            break;
          case exports.LCDScreenSize.DIMENSIONS_1X16:
            this.data.height = 1;
            this.data.width = 16;
            break;
          case exports.LCDScreenSize.DIMENSIONS_2X16:
            this.data.height = 2;
            this.data.width = 16;
            break;
          case exports.LCDScreenSize.DIMENSIONS_4X16:
            this.data.height = 4;
            this.data.width = 16;
            break;
          case exports.LCDScreenSize.DIMENSIONS_2X20:
            this.data.height = 2;
            this.data.width = 20;
            break;
          case exports.LCDScreenSize.DIMENSIONS_4X20:
            this.data.height = 4;
            this.data.width = 20;
            break;
          case exports.LCDScreenSize.DIMENSIONS_2X24:
            this.data.height = 2;
            this.data.width = 24;
            break;
          case exports.LCDScreenSize.DIMENSIONS_1X40:
            this.data.height = 1;
            this.data.width = 40;
            break;
          case exports.LCDScreenSize.DIMENSIONS_2X40:
            this.data.height = 2;
            this.data.width = 40;
            break;
          case exports.LCDScreenSize.DIMENSIONS_4X40:
            this.data.height = 4;
            this.data.width = 40;
            break;
        }
      }
      setAutoFlush(autoFlush) {
        this._assertOpen();
        this.data.autoFlush = autoFlush ? 1 : 0;
      }
      async setCharacterBitmap(font, character, bitmap) {
        this._assertOpen();
        const fontSize = this.getFontSize(font);
        const bp = new BridgePacket();
        if (fontSize.width <= 0) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "invalid arg (getFontSize): " + font);
        if (fontSize.height <= 0) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "invalid arg (getFontSize): " + font);
        bp.set({
          name: "0",
          type: "d",
          value: font
        });
        bp.set({
          name: "1",
          type: "s",
          value: character
        });
        bp.set({
          name: "2",
          type: 'R',
          value: bitmap instanceof Uint8Array ? bitmap : new Uint8Array(bitmap)
        });
        await bp.send(this._ch, 47);
      }
      getMaxCharacters(font) {
        this._assertOpen();
        let maxChars;
        let fontSize;
        switch (this._ch?.chDef.uid) {
          case 343:
          case 342:
            fontSize = this.getFontSize(font);
            if (fontSize.width <= 0) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Font width is <= 0.");
            if (fontSize.height <= 0) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Font height is <= 0.");
            maxChars = Math.floor(Math.min(255, this.data.width / fontSize.width * (this.data.height / fontSize.height)));
            break;
          case 186:
          case 195:
          case 196:
          case 197:
          case 198:
            maxChars = 0xff;
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNEXPECTED);
        }
        return maxChars;
      }
      getFontSize(font) {
        this._assertOpen();
        const fontSize = {
          width: 0,
          height: 0
        };
        switch (font) {
          case exports.LCDFont.DIMENSIONS_6X10:
            fontSize.width = 6;
            fontSize.height = 10;
            break;
          case exports.LCDFont.DIMENSIONS_5X8:
            fontSize.width = 5;
            fontSize.height = 8;
            break;
          case exports.LCDFont.DIMENSIONS_6X12:
            fontSize.width = 6;
            fontSize.height = 12;
            break;
          case exports.LCDFont.USER1:
          case exports.LCDFont.USER2:
            fontSize.width = this.data.fontWidth[font];
            fontSize.height = this.data.fontHeight[font];
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Invalid font.");
        }
        return fontSize;
      }
      async writeBitmap(xpos, ypos, xsize, ysize, bitmap) {
        this._assertOpen();
        const bp = new BridgePacket();
        if (xsize <= 0 || ysize <= 0) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "invalid arg (size cannot be <=0) " + (xsize <= 0 ? xsize : ysize));
        bp.set({
          name: "0",
          type: "d",
          value: xpos
        });
        bp.set({
          name: "1",
          type: "d",
          value: ypos
        });
        bp.set({
          name: "2",
          type: "d",
          value: xsize
        });
        bp.set({
          name: "3",
          type: "d",
          value: ysize
        });
        bp.set({
          name: "4",
          type: 'R',
          value: bitmap instanceof Uint8Array ? bitmap : new Uint8Array(bitmap)
        });
        await bp.send(this._ch, 104);
      }
    }

    /**
     * The LED Array class is used to control addressable LEDs, providing full control over color, brightness, and more.
     * @public
     */
    class LEDArrayBase extends PhidgetChannel {
      /** @internal */
      data;
      constructor(ch) {
        super(ch);
        this._class = exports.ChannelClass.LEDARRAY;
        this.name = "LEDArray";
        this.data = this._initData();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 203:
            break;
          case 206:
            this.data.brightness = bp.entries[0].v;
            this._FIREPropertyChange('Brightness', bp);
            break;
          case 4:
            break;
          case 162:
            this.data.colorOrder = bp.entries[0].v;
            this._FIREPropertyChange('ColorOrder', bp);
            break;
          case 205:
            this.data.gamma = bp.entries[0].v;
            this._FIREPropertyChange('Gamma', bp);
            break;
          case 118:
            break;
          case 56:
            this.data.powerEnabled = bp.entries[0].v;
            this._FIREPropertyChange('PowerEnabled', bp);
            break;
          case 207:
            break;
          case 204:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.INVALID_PACKET, "Unsupported bridge packet: 0x" + bp.vpkt.toString(16));
        }
      }
      /** @internal */
      _initData() {
        return {
          powerEnabled: 2,
          maxLEDCount: 4294967295,
          minLEDCount: 4294967295,
          maxAddress: 4294967295,
          minAddress: 4294967295,
          maxAnimationPatternCount: 4294967295,
          minAnimationPatternCount: 4294967295,
          maxAnimationID: 2147483647,
          minAnimationID: 2147483647,
          maxFadeTime: 4294967295,
          minFadeTime: 4294967295,
          colorOrder: 2147483647,
          gamma: 1e+300,
          maxGamma: 1e+300,
          minGamma: 1e+300,
          brightness: 1e+300,
          maxBrightness: 1e+300,
          minBrightness: 1e+300
        };
      }
      /** @internal */
      _initAfterOpen() {}
      /** @internal */
      async _setDefaults() {}
      /** @internal */
      _hasInitialState() {
        return true;
      }
      /** @internal */
      _fireInitialEvents() {}
      /**
       * The lowest LED address.
       * @throws `PhidgetError`
       */
      get minAddress() {
        return this.getMinAddress();
      }
      /**
       * The highest LED address. When using a `colorOrder` with a white component (e.g., RGBW), this is reduced to 1535.
       * @throws `PhidgetError`
       */
      get maxAddress() {
        return this.getMaxAddress();
      }
      /**
       * The lowest AnimationID.
       * @throws `PhidgetError`
       */
      get minAnimationID() {
        return this.getMinAnimationID();
      }
      /**
       * The highest AnimationID.
       * @throws `PhidgetError`
       */
      get maxAnimationID() {
        return this.getMaxAnimationID();
      }
      /**
       * The minimum size of the LEDArrayColor array when using animations.
       * @throws `PhidgetError`
       */
      get minAnimationPatternCount() {
        return this.getMinAnimationPatternCount();
      }
      /**
       * The maximum size of the LEDArrayColor array when using animations. When using a `colorOrder` with a white component (e.g., RGBW), this is reduced to 96.
       * @throws `PhidgetError`
       */
      get maxAnimationPatternCount() {
        return this.getMaxAnimationPatternCount();
      }
      /**
       * The brightness value will apply to all LEDs. For more information, visit our [LEDArray API Guide](https://www.phidgets.com/docs/LEDArray_API_Guide#Brightness).
       * @throws `PhidgetError`
       */
      get brightness() {
        return this.getBrightness();
      }
      /**
       * The minimum brightness.
       * @throws `PhidgetError`
       */
      get minBrightness() {
        return this.getMinBrightness();
      }
      /**
       * The maximum brightness.
       * @throws `PhidgetError`
       */
      get maxBrightness() {
        return this.getMaxBrightness();
      }
      /**
       * Specify the order of colors expected by your LEDs. For more information, visit our [LEDArray API Guide](https://www.phidgets.com/docs/LEDArray_API_Guide#Color_Order).
       * @throws `PhidgetError`
       */
      get colorOrder() {
        return this.getColorOrder();
      }
      /**
       * The minimum fade time.
       * @throws `PhidgetError`
       */
      get minFadeTime() {
        return this.getMinFadeTime();
      }
      /**
       * The maximum fade time.
       * @throws `PhidgetError`
       */
      get maxFadeTime() {
        return this.getMaxFadeTime();
      }
      /**
       * The gamma value to apply to brightnesses. PC monitors typically to use 2.2. For more information, visit our [LEDArray API Guide](https://www.phidgets.com/docs/LEDArray_API_Guide#Gamma).
       * @throws `PhidgetError`
       */
      get gamma() {
        return this.getGamma();
      }
      /**
       * The minimum value gamma can be set to. Gamma values less than 1 are unsuitable for most applications.
       * @throws `PhidgetError`
       */
      get minGamma() {
        return this.getMinGamma();
      }
      /**
       * The maximum value that gamma can be set to.
       * @throws `PhidgetError`
       */
      get maxGamma() {
        return this.getMaxGamma();
      }
      /**
       * The minimum size of the LEDArrayColor array when using `setLED()` or `setLEDs()`.
       * @throws `PhidgetError`
       */
      get minLEDCount() {
        return this.getMinLEDCount();
      }
      /**
       * The maximum size of the LEDArrayColor array when using `setLED()` or `setLEDs()`. When using a `colorOrder` with a white component (e.g., RGBW), this is reduced to 1536.
       * @throws `PhidgetError`
       */
      get maxLEDCount() {
        return this.getMaxLEDCount();
      }
      /**
       * Control power to all LEDs. For more information, visit our [LEDArray API Guide](https://www.phidgets.com/docs/LEDArray_API_Guide#PowerEnabled).
       * @throws `PhidgetError`
       */
      get powerEnabled() {
        return this.getPowerEnabled();
      }
      /**
       * The lowest LED address.
       * @returns Lowest LED address
       * @throws `PhidgetError`
       */
      getMinAddress() {
        this._assertOpen();
        if (this.data.minAddress === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minAddress;
      }
      /**
       * The highest LED address. When using a `colorOrder` with a white component (e.g., RGBW), this is reduced to 1535.
       * @returns Highest LED address
       * @throws `PhidgetError`
       */
      getMaxAddress() {
        this._assertOpen();
        if (this.data.maxAddress === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxAddress;
      }
      /**
       * The lowest AnimationID.
       * @returns Lowest AnimationID
       * @throws `PhidgetError`
       */
      getMinAnimationID() {
        this._assertOpen();
        if (this.data.minAnimationID === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minAnimationID;
      }
      /**
       * The highest AnimationID.
       * @returns Highest AnimationID
       * @throws `PhidgetError`
       */
      getMaxAnimationID() {
        this._assertOpen();
        if (this.data.maxAnimationID === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxAnimationID;
      }
      /**
       * The minimum size of the LEDArrayColor array when using animations.
       * @returns Minimum pattern count
       * @throws `PhidgetError`
       */
      getMinAnimationPatternCount() {
        this._assertOpen();
        if (this.data.minAnimationPatternCount === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minAnimationPatternCount;
      }
      /**
       * The maximum size of the LEDArrayColor array when using animations. When using a `colorOrder` with a white component (e.g., RGBW), this is reduced to 96.
       * @returns Maximum pattern count
       * @throws `PhidgetError`
       */
      getMaxAnimationPatternCount() {
        this._assertOpen();
        if (this.data.maxAnimationPatternCount === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxAnimationPatternCount;
      }
      /**
       * The brightness value will apply to all LEDs. For more information, visit our [LEDArray API Guide](https://www.phidgets.com/docs/LEDArray_API_Guide#Brightness).
       * @returns Brightness value
       * @throws `PhidgetError`
       */
      getBrightness() {
        this._assertOpen();
        if (this.data.brightness === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.brightness;
      }
      /**
       * The brightness value will apply to all LEDs. For more information, visit our [LEDArray API Guide](https://www.phidgets.com/docs/LEDArray_API_Guide#Brightness).
       * @throws `PhidgetError`
       * @param brightness - Brightness value
       */
      async setBrightness(brightness) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: brightness
        });
        await bp.send(this._ch, 206);
      }
      /**
       * The minimum brightness.
       * @returns Minimum brightness
       * @throws `PhidgetError`
       */
      getMinBrightness() {
        this._assertOpen();
        if (this.data.minBrightness === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minBrightness;
      }
      /**
       * The maximum brightness.
       * @returns Maximum brightness
       * @throws `PhidgetError`
       */
      getMaxBrightness() {
        this._assertOpen();
        if (this.data.maxBrightness === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxBrightness;
      }
      /**
       * Turn off all LEDs. Any active animations will be stopped. For more information, visit our [LEDArray API Guide](https://www.phidgets.com/docs/LEDArray_API_Guide#Clear).
       * @throws `PhidgetError`
       */
      async clearLEDs() {
        this._assertOpen();
        const bp = new BridgePacket();
        await bp.send(this._ch, 4);
      }
      /**
       * Specify the order of colors expected by your LEDs. For more information, visit our [LEDArray API Guide](https://www.phidgets.com/docs/LEDArray_API_Guide#Color_Order).
       * @returns LED Color Order
       * @throws `PhidgetError`
       */
      getColorOrder() {
        this._assertOpen();
        if (this.data.colorOrder === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.colorOrder;
      }
      /**
       * Specify the order of colors expected by your LEDs. For more information, visit our [LEDArray API Guide](https://www.phidgets.com/docs/LEDArray_API_Guide#Color_Order).
       * @throws `PhidgetError`
       * @param colorOrder - LED Color Order
       */
      async setColorOrder(colorOrder) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: colorOrder
        });
        await bp.send(this._ch, 162);
      }
      /**
       * The minimum fade time.
       * @returns Minimum fade time
       * @throws `PhidgetError`
       */
      getMinFadeTime() {
        this._assertOpen();
        if (this.data.minFadeTime === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minFadeTime;
      }
      /**
       * The maximum fade time.
       * @returns Maximum fade time
       * @throws `PhidgetError`
       */
      getMaxFadeTime() {
        this._assertOpen();
        if (this.data.maxFadeTime === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxFadeTime;
      }
      /**
       * The gamma value to apply to brightnesses. PC monitors typically to use 2.2. For more information, visit our [LEDArray API Guide](https://www.phidgets.com/docs/LEDArray_API_Guide#Gamma).
       * @returns Gamma value
       * @throws `PhidgetError`
       */
      getGamma() {
        this._assertOpen();
        if (this.data.gamma === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.gamma;
      }
      /**
       * The gamma value to apply to brightnesses. PC monitors typically to use 2.2. For more information, visit our [LEDArray API Guide](https://www.phidgets.com/docs/LEDArray_API_Guide#Gamma).
       * @throws `PhidgetError`
       * @param gamma - Gamma value
       */
      async setGamma(gamma) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: gamma
        });
        await bp.send(this._ch, 205);
      }
      /**
       * The minimum value gamma can be set to. Gamma values less than 1 are unsuitable for most applications.
       * @returns Minimum gamma
       * @throws `PhidgetError`
       */
      getMinGamma() {
        this._assertOpen();
        if (this.data.minGamma === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minGamma;
      }
      /**
       * The maximum value that gamma can be set to.
       * @returns Maximum gamma
       * @throws `PhidgetError`
       */
      getMaxGamma() {
        this._assertOpen();
        if (this.data.maxGamma === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxGamma;
      }
      /**
       * The minimum size of the LEDArrayColor array when using `setLED()` or `setLEDs()`.
       * @returns Minimum size of the LED array
       * @throws `PhidgetError`
       */
      getMinLEDCount() {
        this._assertOpen();
        if (this.data.minLEDCount === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minLEDCount;
      }
      /**
       * The maximum size of the LEDArrayColor array when using `setLED()` or `setLEDs()`. When using a `colorOrder` with a white component (e.g., RGBW), this is reduced to 1536.
       * @returns Maximum size of the LED array
       * @throws `PhidgetError`
       */
      getMaxLEDCount() {
        this._assertOpen();
        if (this.data.maxLEDCount === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxLEDCount;
      }
      /**
       * Control power to all LEDs. For more information, visit our [LEDArray API Guide](https://www.phidgets.com/docs/LEDArray_API_Guide#PowerEnabled).
       * @returns Control power to all LEDs
       * @throws `PhidgetError`
       */
      getPowerEnabled() {
        this._assertOpen();
        if (this.data.powerEnabled === 2) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return !!this.data.powerEnabled;
      }
      /**
       * Control power to all LEDs. For more information, visit our [LEDArray API Guide](https://www.phidgets.com/docs/LEDArray_API_Guide#PowerEnabled).
       * @throws `PhidgetError`
       * @param powerEnabled - Control power to all LEDs
       */
      async setPowerEnabled(powerEnabled) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: powerEnabled ? 1 : 0
        });
        await bp.send(this._ch, 56);
      }
      /**
       * Disable the specified animation.
       * @throws `PhidgetError`
       * @param animationID - The ID of the animation to disable
       */
      async stopAnimation(animationID) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: animationID
        });
        await bp.send(this._ch, 207);
      }
      /**
       * Restart all animations at the same time.
       * @throws `PhidgetError`
       */
      async synchronizeAnimations() {
        this._assertOpen();
        const bp = new BridgePacket();
        await bp.send(this._ch, 204);
      }
    }

    /** @internal */
    function supportedRFIDProtocol(_ch, val) {
      if (val < exports.RFIDProtocol.EM4100 || val > exports.RFIDProtocol.HID_H10301) return false;
      return true;
    }
    /** @internal */
    function supportedRFIDChipset(_ch, val) {
      if (val < exports.RFIDChipset.T5577 || val > exports.RFIDChipset.EM4305) return false;
      return true;
    }
    /** @internal */
    function supportedLEDArrayAnimationType(_ch, val) {
      if (val < exports.LEDArrayAnimationType.FORWARD_SCROLL || val > exports.LEDArrayAnimationType.REVERSE_SCROLL_MIRROR) return false;
      return true;
    }

    /** @public */
    class LEDArray extends LEDArrayBase {
      /** @internal */
      _transactionLock;
      /** @internal */
      _private;
      constructor(ch) {
        super(ch);
        this._transactionLock = new PhidgetLock();
      }
      /** @internal */
      _initAfterOpen() {
        super._initAfterOpen();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 162:
            {
              const previousMaxLEDCount = this.data.maxLEDCount;
              super._bridgeInput(bp);
              switch (bp.getNumber(0)) {
                case exports.LEDArrayColorOrder.RGB:
                case exports.LEDArrayColorOrder.GRB:
                  this.data.maxLEDCount = 2048;
                  this.data.maxAddress = 2047;
                  this.data.maxAnimationPatternCount = 128;
                  break;
                case exports.LEDArrayColorOrder.RGBW:
                case exports.LEDArrayColorOrder.GRBW:
                  this.data.maxLEDCount = 1536;
                  this.data.maxAddress = 1535;
                  this.data.maxAnimationPatternCount = 96;
                  break;
              }
              if (this.data.maxLEDCount !== previousMaxLEDCount) {
                this._FIREPropertyChange('MaxLEDCount', bp);
                this._FIREPropertyChange('MaxAnimationPatternCount', bp);
                this._FIREPropertyChange('MaxAddress', bp);
              }
              break;
            }
          default:
            super._bridgeInput(bp);
            break;
        }
      }
      async setAnimation(animationID, pattern, animationDescription) {
        this._assertOpen();
        if (pattern.length === 0) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Pattern array cannot be empty");
        if (pattern.length > this.maxAnimationPatternCount) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Pattern must contain " + this.maxAnimationPatternCount + " or fewer elements");
        if (animationDescription.startAddress > this.maxAddress) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Start Address must be less than or equal to " + this.maxAddress);
        if (animationDescription.endAddress > this.maxAddress) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "End Address must be less than or equal to " + this.maxAddress);
        if (animationDescription.endAddress < animationDescription.startAddress) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "End Address must be larger than Start Address");
        if (animationID < this.minAnimationID || animationID > this.maxAnimationID) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Animation ID must be in range: " + this.minAnimationID + " - " + this.maxAnimationID + ".");
        if (animationDescription.time < this.minFadeTime || animationDescription.time > this.maxFadeTime) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Fade Time must be in range: " + this.minFadeTime + " - " + this.maxFadeTime + ".");
        if (!supportedLEDArrayAnimationType(this._ch, animationDescription.animationType)) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Specified AnimationType is unsupported by this device.");
        const patternArrayConverted = pattern.flatMap(l => {
          const rgbArray = [];
          rgbArray.push(l.r ? l.r : 0);
          rgbArray.push(l.g ? l.g : 0);
          rgbArray.push(l.b ? l.b : 0);
          rgbArray.push(l.w ? l.w : 0);
          return rgbArray.flat();
        });
        const segmentLength = animationDescription.endAddress - animationDescription.startAddress + 1;
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: animationID
        });
        bp.set({
          name: "1",
          type: "d",
          value: animationDescription.startAddress
        });
        bp.set({
          name: "2",
          type: "d",
          value: segmentLength
        });
        bp.set({
          name: "3",
          type: "d",
          value: animationDescription.time
        });
        bp.set({
          name: "4",
          type: "d",
          value: animationDescription.animationType
        });
        bp.set({
          name: "5",
          type: 'R',
          value: new Uint8Array(patternArrayConverted)
        });
        await bp.send(this._ch, 203);
      }
      async setLEDs(startAddress, endAddress, leds, fadeTime) {
        this._assertOpen();
        if (leds.length === 0) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "LED array cannot be empty");
        if (startAddress > this.maxAddress) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Start Address must be less than or equal to " + this.maxAddress);
        if (endAddress > this.maxAddress) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "End Address must be less than or equal to " + this.maxAddress);
        if (endAddress < startAddress) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "End Address must be larger than Start Address");
        if (fadeTime < this.minFadeTime || fadeTime > this.maxFadeTime) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Fade Time must be in range: " + this.minFadeTime + " - " + this.maxFadeTime + ".");
        const segmentLength = Math.min(endAddress - startAddress + 1, leds.length);
        const ledArrayConverted = leds.slice(0, segmentLength).flatMap(l => {
          const rgbArray = [];
          rgbArray.push(l.r ? l.r : 0);
          rgbArray.push(l.g ? l.g : 0);
          rgbArray.push(l.b ? l.b : 0);
          rgbArray.push(l.w ? l.w : 0);
          return rgbArray.flat();
        });
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: startAddress
        });
        bp.set({
          name: "1",
          type: "u",
          value: endAddress
        });
        bp.set({
          name: "2",
          type: "u",
          value: fadeTime
        });
        bp.set({
          name: "3",
          type: 'R',
          value: new Uint8Array(ledArrayConverted)
        });
        await bp.send(this._ch, 118);
      }
      async setLED(index, color, fadeTime) {
        this._assertOpen();
        await this.setLEDs(index, index, [color], fadeTime);
      }
    }

    /**
     * The Light Sensor class gathers data from the light sensor on a Phidget board.
     *
     * If you're using a simple 0-5V sensor that does not have its own firmware, use the VoltageInput or VoltageRatioInput class instead, as specified for your device.
     * @public
     */
    class LightSensorBase extends PhidgetChannel {
      /** @internal */
      data;
      onIlluminanceChange = null;
      /** @internal */
      _gotIlluminanceChangeErrorEvent;
      constructor(ch) {
        super(ch);
        this._class = exports.ChannelClass.LIGHT_SENSOR;
        this.name = "LightSensor";
        this.data = this._initData();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 54:
            if (bp.entryCount > 1) this.data.dataInterval = bp.entries[1].v;else this.data.dataInterval = bp.entries[0].v;
            this._FIREPropertyChange('DataInterval', bp);
            this._FIREPropertyChange('DataRate', bp);
            break;
          case 46:
            this.data.illuminanceChangeTrigger = bp.entries[0].v;
            this._FIREPropertyChange('IlluminanceChangeTrigger', bp);
            break;
          case 23:
            {
              this.data.illuminance = bp.entries[0].v;
              if (this._isAttachedDone && this.onIlluminanceChange) {
                try {
                  this.onIlluminanceChange(this.data.illuminance);
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          default:
            throw new PhidgetError(exports.ErrorCode.INVALID_PACKET, "Unsupported bridge packet: 0x" + bp.vpkt.toString(16));
        }
      }
      /** @internal */
      _initData() {
        return {
          dataInterval: 1e+300,
          maxDataInterval: 4294967295,
          minDataRate: 1e+300,
          maxDataRate: 1e+300,
          maxIlluminance: 1e+300,
          maxIlluminanceChangeTrigger: 1e+300,
          minDataInterval: 4294967295,
          minIlluminance: 1e+300,
          minIlluminanceChangeTrigger: 1e+300,
          illuminance: 1e+300,
          illuminanceChangeTrigger: 1e+300
        };
      }
      /** @internal */
      _initAfterOpen() {}
      /** @internal */
      async _setDefaults() {}
      /** @internal */
      _hasInitialState() {
        return true;
      }
      /** @internal */
      _fireInitialEvents() {}
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `IlluminanceChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between `IlluminanceChange` events can also be affected by the `illuminanceChangeTrigger`.
       * @throws `PhidgetError`
       */
      get dataInterval() {
        return this.getDataInterval();
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get minDataInterval() {
        return this.getMinDataInterval();
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataInterval() {
        return this.getMaxDataInterval();
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       */
      get dataRate() {
        return this.getDataRate();
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get minDataRate() {
        return this.getMinDataRate();
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataRate() {
        return this.getMaxDataRate();
      }
      /**
       * The most recent illuminance value that the channel has reported.
       *
       * *   This value will always be between `minIlluminance` and `maxIlluminance`.
       * @throws `PhidgetError`
       */
      get illuminance() {
        return this.getIlluminance();
      }
      /**
       * The minimum value the `IlluminanceChange` event will report.
       * @throws `PhidgetError`
       */
      get minIlluminance() {
        return this.getMinIlluminance();
      }
      /**
       * The maximum value the `IlluminanceChange` event will report.
       * @throws `PhidgetError`
       */
      get maxIlluminance() {
        return this.getMaxIlluminance();
      }
      /**
       * The channel will not issue a `IlluminanceChange` event until the illuminance value has changed by the amount specified by the `illuminanceChangeTrigger`.
       *
       * *   Setting the `illuminanceChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @throws `PhidgetError`
       */
      get illuminanceChangeTrigger() {
        return this.getIlluminanceChangeTrigger();
      }
      /**
       * The minimum value that `illuminanceChangeTrigger` can be set to.
       * @throws `PhidgetError`
       */
      get minIlluminanceChangeTrigger() {
        return this.getMinIlluminanceChangeTrigger();
      }
      /**
       * The maximum value that `illuminanceChangeTrigger` can be set to.
       * @throws `PhidgetError`
       */
      get maxIlluminanceChangeTrigger() {
        return this.getMaxIlluminanceChangeTrigger();
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `IlluminanceChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between `IlluminanceChange` events can also be affected by the `illuminanceChangeTrigger`.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getDataInterval() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.dataInterval;
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `IlluminanceChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between `IlluminanceChange` events can also be affected by the `illuminanceChangeTrigger`.
       * @throws `PhidgetError`
       * @param dataInterval - The data interval value
       */
      async setDataInterval(dataInterval) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: dataInterval
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMinDataInterval() {
        this._assertOpen();
        if (this.data.minDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataInterval;
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMaxDataInterval() {
        this._assertOpen();
        if (this.data.maxDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @returns The data rate for the channel
       * @throws `PhidgetError`
       */
      getDataRate() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return 1000.0 / this.data.dataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       * @param dataRate - The data rate for the channel
       */
      async setDataRate(dataRate) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: Math.round(1000.0 / dataRate)
        });
        bp.set({
          name: "1",
          type: "g",
          value: 1000.0 / dataRate
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMinDataRate() {
        this._assertOpen();
        if (this.data.minDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataRate;
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMaxDataRate() {
        this._assertOpen();
        if (this.data.maxDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataRate;
      }
      /**
       * The most recent illuminance value that the channel has reported.
       *
       * *   This value will always be between `minIlluminance` and `maxIlluminance`.
       * @returns The illuminance value
       * @throws `PhidgetError`
       */
      getIlluminance() {
        this._assertOpen();
        if (this.data.illuminance === 1e+300 || Number.isNaN(this.data.illuminance)) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        if (this.data.illuminance > this.data.maxIlluminance) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE_HIGH);
        if (this.data.illuminance < this.data.minIlluminance) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE_LOW);
        return this.data.illuminance;
      }
      /**
       * The minimum value the `IlluminanceChange` event will report.
       * @returns The illuminance value
       * @throws `PhidgetError`
       */
      getMinIlluminance() {
        this._assertOpen();
        if (this.data.minIlluminance === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minIlluminance;
      }
      /**
       * The maximum value the `IlluminanceChange` event will report.
       * @returns The illuminance value
       * @throws `PhidgetError`
       */
      getMaxIlluminance() {
        this._assertOpen();
        if (this.data.maxIlluminance === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxIlluminance;
      }
      /**
       * The channel will not issue a `IlluminanceChange` event until the illuminance value has changed by the amount specified by the `illuminanceChangeTrigger`.
       *
       * *   Setting the `illuminanceChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getIlluminanceChangeTrigger() {
        this._assertOpen();
        if (this.data.illuminanceChangeTrigger === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.illuminanceChangeTrigger;
      }
      /**
       * The channel will not issue a `IlluminanceChange` event until the illuminance value has changed by the amount specified by the `illuminanceChangeTrigger`.
       *
       * *   Setting the `illuminanceChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @throws `PhidgetError`
       * @param illuminanceChangeTrigger - The change trigger value
       */
      async setIlluminanceChangeTrigger(illuminanceChangeTrigger) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: illuminanceChangeTrigger
        });
        await bp.send(this._ch, 46);
      }
      /**
       * The minimum value that `illuminanceChangeTrigger` can be set to.
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getMinIlluminanceChangeTrigger() {
        this._assertOpen();
        if (this.data.minIlluminanceChangeTrigger === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minIlluminanceChangeTrigger;
      }
      /**
       * The maximum value that `illuminanceChangeTrigger` can be set to.
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getMaxIlluminanceChangeTrigger() {
        this._assertOpen();
        if (this.data.maxIlluminanceChangeTrigger === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxIlluminanceChangeTrigger;
      }
    }

    /** @public */
    class LightSensor extends LightSensorBase {
      /** @internal */
      _errorHandler(code) {
        switch (code) {
          case exports.ErrorEventCode.SATURATION:
            this.data.illuminance = 1e+300;
            this._gotIlluminanceChangeErrorEvent = true;
            break;
        }
      }
    }

    /**
     * The Magnetometer class gathers magnetic compass data from Phidget boards. Phidget magnetometers usually have multiple sensors, each oriented in a different axis, so multiple dimensions of compass bearing can be recorded.
     *
     * If the Phidget you're using also has a gyroscope and an accelerometer, you may want to use the Spatial class in order to get all of the data at the same time, in a single event.
     * @public
     */
    class MagnetometerBase extends PhidgetChannel {
      /** @internal */
      data;
      onMagneticFieldChange = null;
      /** @internal */
      _gotMagneticFieldChangeErrorEvent;
      constructor(ch) {
        super(ch);
        this._class = exports.ChannelClass.MAGNETOMETER;
        this.name = "Magnetometer";
        this.data = this._initData();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 50:
            break;
          case 54:
            if (bp.entryCount > 1) this.data.dataInterval = bp.entries[1].v;else this.data.dataInterval = bp.entries[0].v;
            this._FIREPropertyChange('DataInterval', bp);
            this._FIREPropertyChange('DataRate', bp);
            break;
          case 170:
            this.data.heatingEnabled = bp.entries[0].v;
            this._FIREPropertyChange('HeatingEnabled', bp);
            break;
          case 46:
            this.data.magneticFieldChangeTrigger = bp.entries[0].v;
            this._FIREPropertyChange('MagneticFieldChangeTrigger', bp);
            break;
          case 35:
            break;
          case 37:
            break;
          case 18:
            {
              this.data.magneticField = bp.entries[0].v;
              this.data.timestamp = bp.entries[1].v;
              if (this._isAttachedDone && this.onMagneticFieldChange) {
                try {
                  this.onMagneticFieldChange(this.data.magneticField, this.data.timestamp);
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          default:
            throw new PhidgetError(exports.ErrorCode.INVALID_PACKET, "Unsupported bridge packet: 0x" + bp.vpkt.toString(16));
        }
      }
      /** @internal */
      _initData() {
        return {
          dataInterval: 1e+300,
          maxDataInterval: 4294967295,
          minDataRate: 1e+300,
          maxDataRate: 1e+300,
          maxMagneticField: [1e+300, 1e+300, 1e+300],
          maxMagneticFieldChangeTrigger: 1e+300,
          minDataInterval: 4294967295,
          minMagneticField: [1e+300, 1e+300, 1e+300],
          minMagneticFieldChangeTrigger: 1e+300,
          magneticField: [1e+300, 1e+300, 1e+300],
          magneticFieldChangeTrigger: 1e+300,
          axisCount: 2147483647,
          timestamp: 1e+300,
          heatingEnabled: 2
        };
      }
      /** @internal */
      _initAfterOpen() {}
      /** @internal */
      async _setDefaults() {}
      /** @internal */
      _hasInitialState() {
        return true;
      }
      /** @internal */
      _fireInitialEvents() {}
      /**
       * The number of axes the channel can measure field strength on.
       *
       * *   See your device's User Guide for more information about the number of axes and their orientation.
       * @throws `PhidgetError`
       */
      get axisCount() {
        return this.getAxisCount();
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `MagneticFieldChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between `MagneticFieldChange` events can also be affected by the `magneticFieldChangeTrigger`.
       * @throws `PhidgetError`
       */
      get dataInterval() {
        return this.getDataInterval();
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get minDataInterval() {
        return this.getMinDataInterval();
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataInterval() {
        return this.getMaxDataInterval();
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       */
      get dataRate() {
        return this.getDataRate();
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get minDataRate() {
        return this.getMinDataRate();
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataRate() {
        return this.getMaxDataRate();
      }
      /**
       * Set to TRUE to enable the temperature stabilization feature of this device. This enables onboard heating elements to bring the board up to a known temperature to minimize ambient temerature effects on the sensor's reading. You can leave this setting FALSE to conserve power consumption.
       *
       * If you enable heating, it is strongly recommended to keep the board in its enclosure to keep it insulated from moving air.
       *
       * This property is shared by any and all spatial-related objects on this device (Accelerometer, Gyroscope, Magnetometer, Spatial)
       * @throws `PhidgetError`
       */
      get heatingEnabled() {
        return this.getHeatingEnabled();
      }
      /**
       * The most recent field strength value that the channel has reported.
       *
       * *   This value will always be between `minMagneticField` and `maxMagneticField`.
       * @throws `PhidgetError`
       */
      get magneticField() {
        return this.getMagneticField();
      }
      /**
       * The minimum value the `MagneticFieldChange` event will report.Any readings outside this range will result in a `Saturation` event. This check is done after calibration values have been applied, which will affect your magnetometer's range accordingly.
       * @throws `PhidgetError`
       */
      get minMagneticField() {
        return this.getMinMagneticField();
      }
      /**
       * The maximum value the `MagneticFieldChange` event will report.Any readings outside this range will result in a `Saturation` event. This check is done after calibration values have been applied, which will affect your magnetometer's range accordingly.
       * @throws `PhidgetError`
       */
      get maxMagneticField() {
        return this.getMaxMagneticField();
      }
      /**
       * The channel will not issue a `MagneticFieldChange` event until the field strength value has changed by the amount specified by the `magneticFieldChangeTrigger`.
       *
       * *   Setting the `magneticFieldChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @throws `PhidgetError`
       */
      get magneticFieldChangeTrigger() {
        return this.getMagneticFieldChangeTrigger();
      }
      /**
       * The minimum value that `magneticFieldChangeTrigger` can be set to.
       * @throws `PhidgetError`
       */
      get minMagneticFieldChangeTrigger() {
        return this.getMinMagneticFieldChangeTrigger();
      }
      /**
       * The maximum value that `magneticFieldChangeTrigger` can be set to.
       * @throws `PhidgetError`
       */
      get maxMagneticFieldChangeTrigger() {
        return this.getMaxMagneticFieldChangeTrigger();
      }
      /**
       * The most recent timestamp value that the channel has reported. This is an extremely accurate time measurement streamed from the device.
       *
       * *   If your application requires a time measurement, you should use this value over a local software timestamp.
       * @throws `PhidgetError`
       */
      get timestamp() {
        return this.getTimestamp();
      }
      /**
       * The number of axes the channel can measure field strength on.
       *
       * *   See your device's User Guide for more information about the number of axes and their orientation.
       * @returns The axis count value
       * @throws `PhidgetError`
       */
      getAxisCount() {
        this._assertOpen();
        if (this.data.axisCount === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.axisCount;
      }
      /**
       * Calibrate your device for the environment it will be used in.
       *
       * *   Due to physical location, hard and soft iron offsets, and even bias errors, your device should be calibrated. We have created a calibration program that will provide you with the `MagnetometerCorrectionParameters` for your specific situation. See your device's User Guide for more information.
       * @throws `PhidgetError`
       * @param magneticField - Ambient magnetic field value.
       * @param offset0 - Provided by calibration program.
       * @param offset1 - Provided by calibration program.
       * @param offset2 - Provided by calibration program.
       * @param gain0 - Provided by calibration program.
       * @param gain1 - Provided by calibration program.
       * @param gain2 - Provided by calibration program.
       * @param T0 - Provided by calibration program.
       * @param T1 - Provided by calibration program.
       * @param T2 - Provided by calibration program.
       * @param T3 - Provided by calibration program.
       * @param T4 - Provided by calibration program.
       * @param T5 - Provided by calibration program.
       */
      async setCorrectionParameters(magneticField, offset0, offset1, offset2, gain0, gain1, gain2, T0, T1, T2, T3, T4, T5) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: magneticField
        });
        bp.set({
          name: "1",
          type: "g",
          value: offset0
        });
        bp.set({
          name: "2",
          type: "g",
          value: offset1
        });
        bp.set({
          name: "3",
          type: "g",
          value: offset2
        });
        bp.set({
          name: "4",
          type: "g",
          value: gain0
        });
        bp.set({
          name: "5",
          type: "g",
          value: gain1
        });
        bp.set({
          name: "6",
          type: "g",
          value: gain2
        });
        bp.set({
          name: "7",
          type: "g",
          value: T0
        });
        bp.set({
          name: "8",
          type: "g",
          value: T1
        });
        bp.set({
          name: "9",
          type: "g",
          value: T2
        });
        bp.set({
          name: "10",
          type: "g",
          value: T3
        });
        bp.set({
          name: "11",
          type: "g",
          value: T4
        });
        bp.set({
          name: "12",
          type: "g",
          value: T5
        });
        await bp.send(this._ch, 50);
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `MagneticFieldChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between `MagneticFieldChange` events can also be affected by the `magneticFieldChangeTrigger`.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getDataInterval() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.dataInterval;
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `MagneticFieldChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between `MagneticFieldChange` events can also be affected by the `magneticFieldChangeTrigger`.
       * @throws `PhidgetError`
       * @param dataInterval - The data interval value
       */
      async setDataInterval(dataInterval) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: dataInterval
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMinDataInterval() {
        this._assertOpen();
        if (this.data.minDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataInterval;
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMaxDataInterval() {
        this._assertOpen();
        if (this.data.maxDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @returns The data rate for the channel
       * @throws `PhidgetError`
       */
      getDataRate() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return 1000.0 / this.data.dataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       * @param dataRate - The data rate for the channel
       */
      async setDataRate(dataRate) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: Math.round(1000.0 / dataRate)
        });
        bp.set({
          name: "1",
          type: "g",
          value: 1000.0 / dataRate
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMinDataRate() {
        this._assertOpen();
        if (this.data.minDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataRate;
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMaxDataRate() {
        this._assertOpen();
        if (this.data.maxDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataRate;
      }
      /**
       * Set to TRUE to enable the temperature stabilization feature of this device. This enables onboard heating elements to bring the board up to a known temperature to minimize ambient temerature effects on the sensor's reading. You can leave this setting FALSE to conserve power consumption.
       *
       * If you enable heating, it is strongly recommended to keep the board in its enclosure to keep it insulated from moving air.
       *
       * This property is shared by any and all spatial-related objects on this device (Accelerometer, Gyroscope, Magnetometer, Spatial)
       * @returns Whether self-heating temperature stabilization is enabled
       * @throws `PhidgetError`
       */
      getHeatingEnabled() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 354:
          case 359:
          case 364:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.heatingEnabled === 2) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return !!this.data.heatingEnabled;
      }
      /**
       * Set to TRUE to enable the temperature stabilization feature of this device. This enables onboard heating elements to bring the board up to a known temperature to minimize ambient temerature effects on the sensor's reading. You can leave this setting FALSE to conserve power consumption.
       *
       * If you enable heating, it is strongly recommended to keep the board in its enclosure to keep it insulated from moving air.
       *
       * This property is shared by any and all spatial-related objects on this device (Accelerometer, Gyroscope, Magnetometer, Spatial)
       * @throws `PhidgetError`
       * @param heatingEnabled - Whether self-heating temperature stabilization is enabled
       */
      async setHeatingEnabled(heatingEnabled) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: heatingEnabled ? 1 : 0
        });
        await bp.send(this._ch, 170);
      }
      /**
       * The most recent field strength value that the channel has reported.
       *
       * *   This value will always be between `minMagneticField` and `maxMagneticField`.
       * @returns The channel's measured MagneticField
       * @throws `PhidgetError`
       */
      getMagneticField() {
        var _context;
        this._assertOpen();
        if (_includesInstanceProperty(_context = this.data.magneticField).call(_context, 1e+300)) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.magneticField;
      }
      /**
       * The minimum value the `MagneticFieldChange` event will report.Any readings outside this range will result in a `Saturation` event. This check is done after calibration values have been applied, which will affect your magnetometer's range accordingly.
       * @returns The field strength value
       * @throws `PhidgetError`
       */
      getMinMagneticField() {
        var _context2;
        this._assertOpen();
        if (_includesInstanceProperty(_context2 = this.data.minMagneticField).call(_context2, 1e+300)) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minMagneticField;
      }
      /**
       * The maximum value the `MagneticFieldChange` event will report.Any readings outside this range will result in a `Saturation` event. This check is done after calibration values have been applied, which will affect your magnetometer's range accordingly.
       * @returns The field strength value
       * @throws `PhidgetError`
       */
      getMaxMagneticField() {
        var _context3;
        this._assertOpen();
        if (_includesInstanceProperty(_context3 = this.data.maxMagneticField).call(_context3, 1e+300)) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxMagneticField;
      }
      /**
       * The channel will not issue a `MagneticFieldChange` event until the field strength value has changed by the amount specified by the `magneticFieldChangeTrigger`.
       *
       * *   Setting the `magneticFieldChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getMagneticFieldChangeTrigger() {
        this._assertOpen();
        if (this.data.magneticFieldChangeTrigger === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.magneticFieldChangeTrigger;
      }
      /**
       * The channel will not issue a `MagneticFieldChange` event until the field strength value has changed by the amount specified by the `magneticFieldChangeTrigger`.
       *
       * *   Setting the `magneticFieldChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @throws `PhidgetError`
       * @param magneticFieldChangeTrigger - The change trigger value
       */
      async setMagneticFieldChangeTrigger(magneticFieldChangeTrigger) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: magneticFieldChangeTrigger
        });
        await bp.send(this._ch, 46);
      }
      /**
       * The minimum value that `magneticFieldChangeTrigger` can be set to.
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getMinMagneticFieldChangeTrigger() {
        this._assertOpen();
        if (this.data.minMagneticFieldChangeTrigger === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minMagneticFieldChangeTrigger;
      }
      /**
       * The maximum value that `magneticFieldChangeTrigger` can be set to.
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getMaxMagneticFieldChangeTrigger() {
        this._assertOpen();
        if (this.data.maxMagneticFieldChangeTrigger === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxMagneticFieldChangeTrigger;
      }
      /**
       * Resets the `MagnetometerCorrectionParameters` to their default values.
       *
       * *   Due to physical location, hard and soft iron offsets, and even bias errors, your device should be calibrated. We have created a calibration program that will provide you with the `MagnetometerCorrectionParameters` for your specific situation. See your device's User Guide for more information.
       * @throws `PhidgetError`
       */
      async resetCorrectionParameters() {
        this._assertOpen();
        const bp = new BridgePacket();
        await bp.send(this._ch, 35);
      }
      /**
       * Saves the `MagnetometerCorrectionParameters`.
       *
       * *   Due to physical location, hard and soft iron offsets, and even bias errors, your device should be calibrated. We have created a calibration program that will provide you with the `MagnetometerCorrectionParameters` for your specific situation. See your device's User Guide for more information.
       * @throws `PhidgetError`
       */
      async saveCorrectionParameters() {
        this._assertOpen();
        const bp = new BridgePacket();
        await bp.send(this._ch, 37);
      }
      /**
       * The most recent timestamp value that the channel has reported. This is an extremely accurate time measurement streamed from the device.
       *
       * *   If your application requires a time measurement, you should use this value over a local software timestamp.
       * @returns The timestamp value
       * @throws `PhidgetError`
       */
      getTimestamp() {
        this._assertOpen();
        if (this.data.timestamp === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.timestamp;
      }
    }

    /** @public */
    class Magnetometer extends MagnetometerBase {
      /** @internal */
      transactionLock;
      constructor(ch) {
        super(ch);
        this.transactionLock = new PhidgetLock();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 10:
            if (bp.entryCount > 1) this.data.dataInterval = bp.getNumber(1);else this.data.dataInterval = bp.getNumber(0);
            this._FIREPropertyChange('DataInterval');
            this._FIREPropertyChange('DataRate');
            break;
          case 179:
            this.data.heatingEnabled = bp.entries[0].v;
            this._FIREPropertyChange('HeatingEnabled', bp);
            break;
          default:
            super._bridgeInput(bp);
            break;
        }
      }
      /** @internal */
      _errorHandler(code) {
        switch (code) {
          case exports.ErrorEventCode.SATURATION:
            this.data.magneticField = [1e+300, 1e+300, 1e+300];
            this.data.timestamp = 1e+300;
            this._gotMagneticFieldChangeErrorEvent = true;
            break;
        }
      }
    }

    /**
     * The Motor Position Controller class controlls the position, velocity and acceleration of the attached motor. It also contains various other control and monitoring functions that aid in the control of the motor.
     *
     * For specifics on how to use this class, we recommend watching our video on the [Phidget Motor Position Controller](https://www.youtube.com/watch?v=0cQlxNd7dk4) class.
     * @public
     */
    class MotorPositionControllerBase extends PhidgetChannel {
      /** @internal */
      data;
      onPositionChange = null;
      /** @internal */
      _gotPositionChangeErrorEvent;
      onExpectedPositionChange = null;
      /** @internal */
      _gotExpectedPositionChangeErrorEvent;
      onDutyCycleUpdate = null;
      /** @internal */
      _gotDutyCycleUpdateErrorEvent;
      constructor(ch) {
        super(ch);
        this._class = exports.ChannelClass.MOTOR_POSITION_CONTROLLER;
        this.name = "MotorPositionController";
        this.data = this._initData();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 40:
            this.data.acceleration = bp.entries[0].v;
            this._FIREPropertyChange('Acceleration', bp);
            break;
          case 51:
            this.data.currentLimit = bp.entries[0].v;
            this._FIREPropertyChange('CurrentLimit', bp);
            break;
          case 119:
            this.data.currentRegulatorGain = bp.entries[0].v;
            this._FIREPropertyChange('CurrentRegulatorGain', bp);
            break;
          case 54:
            if (bp.entryCount > 1) this.data.dataInterval = bp.entries[1].v;else this.data.dataInterval = bp.entries[0].v;
            this._FIREPropertyChange('DataInterval', bp);
            this._FIREPropertyChange('DataRate', bp);
            break;
          case 120:
            this.data.deadBand = bp.entries[0].v;
            this._FIREPropertyChange('DeadBand', bp);
            break;
          case 57:
            this.data.engaged = bp.entries[0].v;
            this._FIREPropertyChange('Engaged', bp);
            break;
          case 189:
            this.data.enableExpectedPosition = bp.entries[0].v;
            this._FIREPropertyChange('EnableExpectedPosition', bp);
            break;
          case 146:
            break;
          case 193:
            this.data.failsafeBrakingEnabled = bp.entries[0].v;
            this._FIREPropertyChange('FailsafeBrakingEnabled', bp);
            break;
          case 192:
            this.data.failsafeCurrentLimit = bp.entries[0].v;
            this._FIREPropertyChange('FailsafeCurrentLimit', bp);
            break;
          case 58:
            this.data.fanMode = bp.entries[0].v;
            this._FIREPropertyChange('FanMode', bp);
            break;
          case 184:
            this.data.inductance = bp.entries[0].v;
            this._FIREPropertyChange('Inductance', bp);
            break;
          case 65:
            this.data.IOMode = bp.entries[0].v;
            this._FIREPropertyChange('IOMode', bp);
            break;
          case 136:
            this.data.kd = bp.entries[0].v;
            this._FIREPropertyChange('Kd', bp);
            break;
          case 142:
            this.data.ki = bp.entries[0].v;
            this._FIREPropertyChange('Ki', bp);
            break;
          case 135:
            this.data.kp = bp.entries[0].v;
            this._FIREPropertyChange('Kp', bp);
            break;
          case 187:
            this.data.positionType = bp.entries[0].v;
            this._FIREPropertyChange('PositionType', bp);
            break;
          case 147:
            break;
          case 141:
            this.data.stallVelocity = bp.entries[0].v;
            this._FIREPropertyChange('StallVelocity', bp);
            break;
          case 194:
            this.data.surgeCurrentLimit = bp.entries[0].v;
            this._FIREPropertyChange('SurgeCurrentLimit', bp);
            break;
          case 83:
            this.data.targetPosition = bp.entries[0].v;
            this._FIREPropertyChange('TargetPosition', bp);
            break;
          case 55:
            this.data.velocityLimit = bp.entries[0].v;
            this._FIREPropertyChange('VelocityLimit', bp);
            break;
          case 16:
            {
              this.data.dutyCycle = bp.entries[0].v;
              if (this._isAttachedDone && this.onDutyCycleUpdate) {
                try {
                  this.onDutyCycleUpdate(this.data.dutyCycle);
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          default:
            throw new PhidgetError(exports.ErrorCode.INVALID_PACKET, "Unsupported bridge packet: 0x" + bp.vpkt.toString(16));
        }
      }
      /** @internal */
      _initData() {
        return {
          positionOffset: 0,
          dataInterval: 1e+300,
          minDataInterval: 4294967295,
          maxDataInterval: 4294967295,
          minDataRate: 1e+300,
          maxDataRate: 1e+300,
          currentLimit: 1e+300,
          maxCurrentLimit: 1e+300,
          minCurrentLimit: 1e+300,
          surgeCurrentLimit: 1e+300,
          maxSurgeCurrentLimit: 1e+300,
          minSurgeCurrentLimit: 1e+300,
          currentRegulatorGain: 1e+300,
          activeCurrentLimit: 1e+300,
          dutyCycle: 1e+300,
          engaged: 2,
          maxCurrentRegulatorGain: 1e+300,
          minCurrentRegulatorGain: 1e+300,
          velocityLimit: 1e+300,
          minVelocityLimit: 1e+300,
          maxVelocityLimit: 1e+300,
          maxAcceleration: 1e+300,
          minAcceleration: 1e+300,
          acceleration: 1e+300,
          targetPosition: 9223372036854776000,
          position: 9223372036854776000,
          maxPosition: 9223372036854776000,
          minPosition: 9223372036854776000,
          enableExpectedPosition: 2,
          expectedPosition: 9223372036854776000,
          rescaleFactor: 1e+300,
          fanMode: 2147483647,
          deadBand: 4294967295,
          kp: 1e+300,
          kd: 1e+300,
          ki: 1e+300,
          IOMode: 2147483647,
          stallVelocity: 1e+300,
          minStallVelocity: 1e+300,
          maxStallVelocity: 1e+300,
          maxFailsafeTime: 4294967295,
          minFailsafeTime: 4294967295,
          inductance: 1e+300,
          maxInductance: 1e+300,
          minInductance: 1e+300,
          positionType: 2147483647,
          failsafeCurrentLimit: 1e+300,
          failsafeBrakingEnabled: 2,
          normalizePID: 2
        };
      }
      /** @internal */
      _initAfterOpen() {}
      /** @internal */
      async _setDefaults() {}
      /** @internal */
      _hasInitialState() {
        return true;
      }
      /** @internal */
      _fireInitialEvents() {}
      /**
       * The rate at which the controller can change the motor's velocity.
       *
       * *   Use the `rescaleFactor` to convert the units of this property to more intuitive units, such as rotations or degrees.
       *
       *
       * For more information about `acceleration`, visit our [MotorPositionController API Guide](https://www.phidgets.com/docs/MotorPositionController_API_Guide#Acceleration)
       * @throws `PhidgetError`
       */
      get acceleration() {
        return this.getAcceleration();
      }
      /**
       * The minimum value that `acceleration` can be set to.
       *
       * *   Use the `rescaleFactor` to convert the units of this property to more intuitive units, such as rotations or degrees.
       * @throws `PhidgetError`
       */
      get minAcceleration() {
        return this.getMinAcceleration();
      }
      /**
       * The maximum value that `acceleration` can be set to.
       *
       * *   Use the `rescaleFactor` to convert the units of this property to more intuitive units, such as rotations or degrees.
       * @throws `PhidgetError`
       */
      get maxAcceleration() {
        return this.getMaxAcceleration();
      }
      /**
       * The current limit that the controller is actively following. The `surgeCurrentLimit`, `currentLimit`, and temperature will impact this value.
       * @throws `PhidgetError`
       */
      get activeCurrentLimit() {
        return this.getActiveCurrentLimit();
      }
      /**
       * The controller will limit the current through the motor to the `currentLimit` value.
       *
       *
       * For more information about `currentLimit`, visit our [MotorPositionController API Guide](https://www.phidgets.com/docs/MotorPositionController_API_Guide#Current_Limit)
       * @throws `PhidgetError`
       */
      get currentLimit() {
        return this.getCurrentLimit();
      }
      /**
       * The minimum current limit that can be set for the device.
       * @throws `PhidgetError`
       */
      get minCurrentLimit() {
        return this.getMinCurrentLimit();
      }
      /**
       * The maximum current limit that can be set for the device.
       * @throws `PhidgetError`
       */
      get maxCurrentLimit() {
        return this.getMaxCurrentLimit();
      }
      /**
       * Depending on power supply voltage and motor coil inductance, current through the motor can change relatively slowly or extremely rapidly. A physically larger DC Motor will typically have a lower inductance, requiring a higher current regulator gain. A higher power supply voltage will result in motor current changing more rapidly, requiring a higher current regulator gain. If the current regulator gain is too small, spikes in current will occur, causing large variations in torque, and possibly damaging the motor controller. If the current regulator gain is too high, the current will jitter, causing the motor to sound 'rough', especially when changing directions. Each DC Motor we sell specifies a suitable current regulator gain.
       * @throws `PhidgetError`
       */
      get currentRegulatorGain() {
        return this.getCurrentRegulatorGain();
      }
      /**
       * The minimum current regulator gain for the device.
       * @throws `PhidgetError`
       */
      get minCurrentRegulatorGain() {
        return this.getMinCurrentRegulatorGain();
      }
      /**
       * The maximum current regulator gain for the device.
       * @throws `PhidgetError`
       */
      get maxCurrentRegulatorGain() {
        return this.getMaxCurrentRegulatorGain();
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `PositionChange` / `DutyCycleUpdate` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * @throws `PhidgetError`
       */
      get dataInterval() {
        return this.getDataInterval();
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get minDataInterval() {
        return this.getMinDataInterval();
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataInterval() {
        return this.getMaxDataInterval();
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       */
      get dataRate() {
        return this.getDataRate();
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get minDataRate() {
        return this.getMinDataRate();
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataRate() {
        return this.getMaxDataRate();
      }
      /**
       * `deadBand` specifies a a region around the `targetPosition` (`targetPosition` +/- `deadBand`) where control of the motor is relaxed.
       *
       * *   Use the `rescaleFactor` to convert the units of this property to more intuitive units, such as rotations or degrees.
       *
       *
       * For more information about `deadBand`, visit our [MotorPositionController API Guide](https://www.phidgets.com/docs/MotorPositionController_API_Guide#Deadband)
       * @throws `PhidgetError`
       */
      get deadBand() {
        return this.getDeadBand();
      }
      /**
       * The most recent `dutyCycle` value that the controller has reported.
       *
       * *   This value will be between -1 and 1 where a sign change (±) is indicitave of a direction change.
       * *   `dutyCycle` is an indication of the average voltage across the motor. At a constant load, an increase in `dutyCycle` indicates an increase in motor speed.
       *
       *
       * For more information about `dutyCycle`, visit our [MotorPositionController API Guide](https://www.phidgets.com/docs/MotorPositionController_API_Guide#Duty_Cycle)
       * @throws `PhidgetError`
       */
      get dutyCycle() {
        return this.getDutyCycle();
      }
      /**
       * When engaged, the motor has the ability to be positioned. When disengaged, the controller will stop powering to your motor, it will instead be in a freewheel state.
       *
       *
       * For more information about `engaged`, visit our [MotorPositionController API Guide](https://www.phidgets.com/docs/MotorPositionController_API_Guide#Engage_Motor)
       * @throws `PhidgetError`
       */
      get engaged() {
        return this.getEngaged();
      }
      /**
       * This controller uses trapezoidal motion profiling combined with a PID loop to accurately track position. The `expectedPosition` represents the current position the controller is tracking along the trapezoidal motion curve. The error of your PID loop is calculated by taking the difference of `position` and `expectedPosition`. You can use this value to verify your controller is working as expected.
       *
       * *   Set `enableExpectedPosition` to **TRUE** to enable the change event for this property.
       * *   Use the `rescaleFactor` to convert the units of this property to more intuitive units, such as rotations or degrees.
       * @throws `PhidgetError`
       */
      get expectedPosition() {
        return this.getExpectedPosition();
      }
      /**
       * When enabled, the `expectedPosition` will be sent back from the controller.
       * @throws `PhidgetError`
       */
      get enableExpectedPosition() {
        return this.getEnableExpectedPosition();
      }
      /**
       * This setting allows you to choose whether motor will forcibly stop once it enters a **FAILSAFE** state.
       *
       * *   A setting of FALSE will simply stop applying power to the motor, allowing it to spin down naturally.
       * *   A setting of TRUE will apply braking up to the `failsafeCurrentLimit`, actively stopping the motor
       *
       *
       * For more information about `failsafeBrakingEnabled`, visit our [MotorPositionController API Guide](https://www.phidgets.com/docs/MotorPositionController_API_Guide#Failsafe_Braking_Enabled)
       * @throws `PhidgetError`
       */
      get failsafeBrakingEnabled() {
        return this.getFailsafeBrakingEnabled();
      }
      /**
       * When the controller enters a **FAILSAFE** state, the controller will limit the current through the motor to the `failsafeCurrentLimit` value.
       *
       *
       * For more information about `failsafeCurrentLimit`, visit our [MotorPositionController API Guide](https://www.phidgets.com/docs/MotorPositionController_API_Guide#Failsafe_Current_Limit)
       * @throws `PhidgetError`
       */
      get failsafeCurrentLimit() {
        return this.getFailsafeCurrentLimit();
      }
      /**
       * The minimum value that `failsafeTime` can be set to when calling `enableFailsafe()`.
       * @throws `PhidgetError`
       */
      get minFailsafeTime() {
        return this.getMinFailsafeTime();
      }
      /**
       * The maximum value that `failsafeTime` can be set to when calling `enableFailsafe()`.
       * @throws `PhidgetError`
       */
      get maxFailsafeTime() {
        return this.getMaxFailsafeTime();
      }
      /**
       * The `fanMode` dictates the operating condition of the fan.
       *
       * *   Choose between on, off, or automatic (based on temperature).
       * *   If the `fanMode` is set to automatic, the fan will turn on when the temperature reaches 70°C and it will remain on until the temperature falls below 55°C.
       * *   If the `fanMode` is off, the controller will still turn on the fan if the temperature reaches 85°C and it will remain on until it falls below 70°C.
       * @throws `PhidgetError`
       */
      get fanMode() {
        return this.getFanMode();
      }
      /**
       * The controller will attempt to measure the inductance of your motor when opened. This value is used to improve control of the motor.
       *
       * *   Set this value during the `Phidget.Attach` event to skip motor characterization (including the audible beeps). You can use a previously saved `inductance` value, or information from your motor's datasheet.
       *
       *
       * For more information about `inductance`, visit our [MotorPositionController API Guide](https://www.phidgets.com/docs/MotorPositionController_API_Guide#Motor_Inductance)
       * @throws `PhidgetError`
       */
      get inductance() {
        return this.getInductance();
      }
      /**
       * The minimum value that `inductance` can be set to. See `inductance` for details.
       * @throws `PhidgetError`
       */
      get minInductance() {
        return this.getMinInductance();
      }
      /**
       * The maximum value that `inductance` can be set to. See `inductance` for details.
       * @throws `PhidgetError`
       */
      get maxInductance() {
        return this.getMaxInductance();
      }
      /**
       * The encoder interface mode. Match the mode to the type of encoder you have attached.
       *
       * *   It is recommended to only change this when the encoder disabled in order to avoid unexpected results.
       * @throws `PhidgetError`
       */
      get IOMode() {
        return this.getIOMode();
      }
      /**
       * Derivative gain constant. A higher `kd` will help reduce oscillations.
       *
       *
       * For more information about `kd`, visit our [MotorPositionController API Guide](https://www.phidgets.com/docs/MotorPositionController_API_Guide#Tunings_Constants_\(Kp,_Ki,_Kd\))
       * @throws `PhidgetError`
       */
      get kd() {
        return this.getKd();
      }
      /**
       * Integral gain constant. The integral term will help eliminate steady-state error.
       *
       *
       * For more information about `ki`, visit our [MotorPositionController API Guide](https://www.phidgets.com/docs/MotorPositionController_API_Guide#Tunings_Constants_\(Kp,_Ki,_Kd\))
       * @throws `PhidgetError`
       */
      get ki() {
        return this.getKi();
      }
      /**
       * Proportional gain constant. A small `kp` value will result in a less responsive controller, however, if `kp` is too high, the system can become unstable.
       *
       *
       * For more information about `kp`, visit our [MotorPositionController API Guide](https://www.phidgets.com/docs/MotorPositionController_API_Guide#Tunings_Constants_\(Kp,_Ki,_Kd\))
       * @throws `PhidgetError`
       */
      get kp() {
        return this.getKp();
      }
      /**
       * Set this parameter to TRUE to adjust PID math to standardized units.
       * @throws `PhidgetError`
       */
      get normalizePID() {
        return this.getNormalizePID();
      }
      set normalizePID(normalizePID) {
        this.setNormalizePID(normalizePID);
      }
      /**
       * The most recent position value that the controller has reported.
       *
       * *   Use the `rescaleFactor` to convert the units of this property to more intuitive units, such as rotations or degrees.
       *
       *
       * For more information about `position`, visit our [MotorPositionController API Guide](https://www.phidgets.com/docs/MotorPositionController_API_Guide#Position)
       * @throws `PhidgetError`
       */
      get position() {
        return this.getPosition();
      }
      /**
       * The minimum value that `targetPosition` can be set to.
       *
       * *   Use the `rescaleFactor` to convert the units of this property to more intuitive units, such as rotations or degrees.
       * @throws `PhidgetError`
       */
      get minPosition() {
        return this.getMinPosition();
      }
      /**
       * The maximum value that `targetPosition` can be set to.
       *
       * *   Use the `rescaleFactor` to convert the units of this property to more intuitive units, such as rotations or degrees.
       * @throws `PhidgetError`
       */
      get maxPosition() {
        return this.getMaxPosition();
      }
      /**
       * Determines whether the controller uses the hall effect sensors or an encoder for position information. This setting is locked in once the channel is `engaged` and cannot be changed until the channel is reset.
       * @throws `PhidgetError`
       */
      get positionType() {
        return this.getPositionType();
      }
      /**
       * Change the units of your parameters so that your application is more intuitive.
       *
       * *   Units for `position`, `targetPosition`, `velocityLimit`, `acceleration`, and `deadBand` can be set by the user through the `rescaleFactor`. The `rescaleFactor` allows you to use more intuitive units such as rotations, or degrees.
       *
       *
       * For more information about `rescaleFactor`, visit our [MotorPositionController API Guide](https://www.phidgets.com/docs/MotorPositionController_API_Guide#Rescale_Factor)
       * @throws `PhidgetError`
       */
      get rescaleFactor() {
        return this.getRescaleFactor();
      }
      set rescaleFactor(rescaleFactor) {
        this.setRescaleFactor(rescaleFactor);
      }
      /**
       * Before reading this description, it is important to note the difference between the units of `stallVelocity` and `dutyCycle`.
       *
       * *   `dutyCycle` is a number between -1 and 1 with units of 'duty cycle'. It simply represents the average voltage across the motor.
       * *   `stallVelocity` represents a real velocity (e.g. m/s, RPM, etc.) and the units are determined by the `rescaleFactor`. With a `rescaleFactor` of 1, the default units would be in commutations per second.
       *
       * If the load on your motor is large, your motor may begin rotating more slowly, or even fully stall. Depending on the voltage across your motor, this may result in a large amount of current through both the controller and the motor. In order to prevent damage in these situations, you can use the `stallVelocity` property.
       *
       * The `stallVelocity` should be set to the lowest velocity you would expect from your motor. The controller will then monitor the motor's velocity, as well as the `dutyCycle`, and prevent a 'dangerous stall' from occuring. If the controller detects a dangerous stall, it will immediately disengage the motor (i.e. `engaged` will be set to false) and an error will be reported to your program.
       *
       * *   A 'dangerous stall' will occur faster when the `dutyCycle` is higher (i.e. when the average voltage across the motor is higher)
       * *   A 'dangerous stall' will occur faster as (`stallVelocity` - motor velocity) becomes larger .
       *
       * Setting `stallVelocity` to 0 will turn off stall protection functionality.
       * @throws `PhidgetError`
       */
      get stallVelocity() {
        return this.getStallVelocity();
      }
      /**
       * The lower bound of `stallVelocity`.
       * @throws `PhidgetError`
       */
      get minStallVelocity() {
        return this.getMinStallVelocity();
      }
      /**
       * The upper bound of `stallVelocity`.
       * @throws `PhidgetError`
       */
      get maxStallVelocity() {
        return this.getMaxStallVelocity();
      }
      /**
       * The `surgeCurrentLimit` allows for increased performance from your motor. The controller will limit the current through your motor to the `surgeCurrentLimit` briefly, then scale current down to the `currentLimit`.
       *
       * *   View `activeCurrentLimit` for information about what current limit the controller is actively following.
       *
       *
       * For more information about `surgeCurrentLimit`, visit our [MotorPositionController API Guide](https://www.phidgets.com/docs/MotorPositionController_API_Guide#Surge_Current_Limit)
       * @throws `PhidgetError`
       */
      get surgeCurrentLimit() {
        return this.getSurgeCurrentLimit();
      }
      /**
       * The minimum value that `surgeCurrentLimit` can be set to.
       * @throws `PhidgetError`
       */
      get minSurgeCurrentLimit() {
        return this.getMinSurgeCurrentLimit();
      }
      /**
       * The maximum value that `surgeCurrentLimit` can be set to.
       * @throws `PhidgetError`
       */
      get maxSurgeCurrentLimit() {
        return this.getMaxSurgeCurrentLimit();
      }
      /**
       * When the controller is engaged and the `targetPosition` is set, the motor will attempt to reach the `targetPosition`.
       *
       * *   If the `deadBand` is non-zero, the final position of the motor may not match the `targetPosition`
       * *   Use the `rescaleFactor` to convert the units of this property to more intuitive units, such as rotations or degrees.
       *
       *
       * For more information about `targetPosition`, visit our [MotorPositionController API Guide](https://www.phidgets.com/docs/MotorPositionController_API_Guide#Target_Position)
       * @throws `PhidgetError`
       */
      get targetPosition() {
        return this.getTargetPosition();
      }
      /**
       * The controller will attempt to limit the motor's velocity to this value.
       *
       * *   The `velocityLimit` may be exceeded to track the `targetPosition` more accurately.
       * *   Use the `rescaleFactor` to convert the units of this property to more intuitive units, such as rotations or degrees.
       *
       *
       * For more information about `velocityLimit`, visit our [MotorPositionController API Guide](https://www.phidgets.com/docs/MotorPositionController_API_Guide#Velocity_Limit)
       * @throws `PhidgetError`
       */
      get velocityLimit() {
        return this.getVelocityLimit();
      }
      /**
       * The minimum value that `velocityLimit` can be set to.
       *
       * *   Use the `rescaleFactor` to convert the units of this property to more intuitive units, such as rotations or degrees.
       * @throws `PhidgetError`
       */
      get minVelocityLimit() {
        return this.getMinVelocityLimit();
      }
      /**
       * The maximum value that `velocityLimit` can be set to.
       *
       * *   Use the `rescaleFactor` to convert the units of this property to more intuitive units, such as rotations or degrees.
       * @throws `PhidgetError`
       */
      get maxVelocityLimit() {
        return this.getMaxVelocityLimit();
      }
      /**
       * The current limit that the controller is actively following. The `surgeCurrentLimit`, `currentLimit`, and temperature will impact this value.
       * @returns The active current limit value
       * @throws `PhidgetError`
       */
      getActiveCurrentLimit() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 281:
          case 288:
          case 304:
          case 311:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.activeCurrentLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.activeCurrentLimit;
      }
      /**
       * The controller will limit the current through the motor to the `currentLimit` value.
       *
       *
       * For more information about `currentLimit`, visit our [MotorPositionController API Guide](https://www.phidgets.com/docs/MotorPositionController_API_Guide#Current_Limit)
       * @returns Motor current limit
       * @throws `PhidgetError`
       */
      getCurrentLimit() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 292:
          case 295:
          case 298:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.currentLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.currentLimit;
      }
      /**
       * The controller will limit the current through the motor to the `currentLimit` value.
       *
       *
       * For more information about `currentLimit`, visit our [MotorPositionController API Guide](https://www.phidgets.com/docs/MotorPositionController_API_Guide#Current_Limit)
       * @throws `PhidgetError`
       * @param currentLimit - Motor current limit
       */
      async setCurrentLimit(currentLimit) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: currentLimit
        });
        await bp.send(this._ch, 51);
      }
      /**
       * The minimum current limit that can be set for the device.
       * @returns Minimum current limit
       * @throws `PhidgetError`
       */
      getMinCurrentLimit() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 292:
          case 295:
          case 298:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.minCurrentLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minCurrentLimit;
      }
      /**
       * The maximum current limit that can be set for the device.
       * @returns Maximum current limit
       * @throws `PhidgetError`
       */
      getMaxCurrentLimit() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 292:
          case 295:
          case 298:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.maxCurrentLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxCurrentLimit;
      }
      /**
       * Depending on power supply voltage and motor coil inductance, current through the motor can change relatively slowly or extremely rapidly. A physically larger DC Motor will typically have a lower inductance, requiring a higher current regulator gain. A higher power supply voltage will result in motor current changing more rapidly, requiring a higher current regulator gain. If the current regulator gain is too small, spikes in current will occur, causing large variations in torque, and possibly damaging the motor controller. If the current regulator gain is too high, the current will jitter, causing the motor to sound 'rough', especially when changing directions. Each DC Motor we sell specifies a suitable current regulator gain.
       * @returns Current Regulator Gain
       * @throws `PhidgetError`
       */
      getCurrentRegulatorGain() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 255:
          case 261:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.currentRegulatorGain === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.currentRegulatorGain;
      }
      /**
       * Depending on power supply voltage and motor coil inductance, current through the motor can change relatively slowly or extremely rapidly. A physically larger DC Motor will typically have a lower inductance, requiring a higher current regulator gain. A higher power supply voltage will result in motor current changing more rapidly, requiring a higher current regulator gain. If the current regulator gain is too small, spikes in current will occur, causing large variations in torque, and possibly damaging the motor controller. If the current regulator gain is too high, the current will jitter, causing the motor to sound 'rough', especially when changing directions. Each DC Motor we sell specifies a suitable current regulator gain.
       * @throws `PhidgetError`
       * @param currentRegulatorGain - Current Regulator Gain
       */
      async setCurrentRegulatorGain(currentRegulatorGain) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: currentRegulatorGain
        });
        await bp.send(this._ch, 119);
      }
      /**
       * The minimum current regulator gain for the device.
       * @returns Minimum current regulator gain
       * @throws `PhidgetError`
       */
      getMinCurrentRegulatorGain() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 255:
          case 261:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.minCurrentRegulatorGain === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minCurrentRegulatorGain;
      }
      /**
       * The maximum current regulator gain for the device.
       * @returns Maximum current regulator gain
       * @throws `PhidgetError`
       */
      getMaxCurrentRegulatorGain() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 255:
          case 261:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.maxCurrentRegulatorGain === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxCurrentRegulatorGain;
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `PositionChange` / `DutyCycleUpdate` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getDataInterval() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.dataInterval;
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `PositionChange` / `DutyCycleUpdate` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * @throws `PhidgetError`
       * @param dataInterval - The data interval value
       */
      async setDataInterval(dataInterval) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: dataInterval
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMinDataInterval() {
        this._assertOpen();
        if (this.data.minDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataInterval;
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMaxDataInterval() {
        this._assertOpen();
        if (this.data.maxDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @returns The data rate for the channel
       * @throws `PhidgetError`
       */
      getDataRate() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return 1000.0 / this.data.dataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       * @param dataRate - The data rate for the channel
       */
      async setDataRate(dataRate) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: Math.round(1000.0 / dataRate)
        });
        bp.set({
          name: "1",
          type: "g",
          value: 1000.0 / dataRate
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMinDataRate() {
        this._assertOpen();
        if (this.data.minDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataRate;
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMaxDataRate() {
        this._assertOpen();
        if (this.data.maxDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataRate;
      }
      /**
       * The most recent `dutyCycle` value that the controller has reported.
       *
       * *   This value will be between -1 and 1 where a sign change (±) is indicitave of a direction change.
       * *   `dutyCycle` is an indication of the average voltage across the motor. At a constant load, an increase in `dutyCycle` indicates an increase in motor speed.
       *
       *
       * For more information about `dutyCycle`, visit our [MotorPositionController API Guide](https://www.phidgets.com/docs/MotorPositionController_API_Guide#Duty_Cycle)
       * @returns The duty cycle value.
       * @throws `PhidgetError`
       */
      getDutyCycle() {
        this._assertOpen();
        if (this.data.dutyCycle === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.dutyCycle;
      }
      /**
       * When engaged, the motor has the ability to be positioned. When disengaged, the controller will stop powering to your motor, it will instead be in a freewheel state.
       *
       *
       * For more information about `engaged`, visit our [MotorPositionController API Guide](https://www.phidgets.com/docs/MotorPositionController_API_Guide#Engage_Motor)
       * @returns The engaged value.
       * @throws `PhidgetError`
       */
      getEngaged() {
        this._assertOpen();
        if (this.data.engaged === 2) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return !!this.data.engaged;
      }
      /**
       * When engaged, the motor has the ability to be positioned. When disengaged, the controller will stop powering to your motor, it will instead be in a freewheel state.
       *
       *
       * For more information about `engaged`, visit our [MotorPositionController API Guide](https://www.phidgets.com/docs/MotorPositionController_API_Guide#Engage_Motor)
       * @throws `PhidgetError`
       * @param engaged - The engaged value.
       */
      async setEngaged(engaged) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: engaged ? 1 : 0
        });
        await bp.send(this._ch, 57);
      }
      /**
       * When enabled, the `expectedPosition` will be sent back from the controller.
       * @throws `PhidgetError`
       * @param enableExpectedPosition - Enable expected position feedback
       */
      async setEnableExpectedPosition(enableExpectedPosition) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: enableExpectedPosition ? 1 : 0
        });
        await bp.send(this._ch, 189);
      }
      /**
       * When enabled, the `expectedPosition` will be sent back from the controller.
       * @returns Enable expected position feedback
       * @throws `PhidgetError`
       */
      getEnableExpectedPosition() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 281:
          case 288:
          case 304:
          case 311:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.enableExpectedPosition === 2) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return !!this.data.enableExpectedPosition;
      }
      /**
       * Enables the **failsafe** feature for the channel, with the specified **failsafe time**.
       *
       * Enabling the failsafe feature starts a recurring **failsafe timer** for the channel. Once the failsafe is enabled, the timer must be reset within the specified time or the channel will enter a **failsafe state**. For Motor Position Controller channels, this will cut power to the motor, allowing it to coast (freewheel) instead. The failsafe timer can be reset by using any API call **_except_** for the following:
       *
       * *   `setRescaleFactor()`
       * *   `addPositionOffset()`
       * *   `setNormalizePID()`
       * *   'get' API calls
       *
       * For more information about failsafe, visit our [Failsafe Guide](https://www.phidgets.com/docs/Failsafe_Guide).
       * @throws `PhidgetError`
       * @param failsafeTime - Failsafe timeout in milliseconds
       */
      async enableFailsafe(failsafeTime) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: failsafeTime
        });
        await bp.send(this._ch, 146);
      }
      /**
       * This setting allows you to choose whether motor will forcibly stop once it enters a **FAILSAFE** state.
       *
       * *   A setting of FALSE will simply stop applying power to the motor, allowing it to spin down naturally.
       * *   A setting of TRUE will apply braking up to the `failsafeCurrentLimit`, actively stopping the motor
       *
       *
       * For more information about `failsafeBrakingEnabled`, visit our [MotorPositionController API Guide](https://www.phidgets.com/docs/MotorPositionController_API_Guide#Failsafe_Braking_Enabled)
       * @returns Enables failsafe braking
       * @throws `PhidgetError`
       */
      getFailsafeBrakingEnabled() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 281:
          case 288:
          case 304:
          case 311:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.failsafeBrakingEnabled === 2) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return !!this.data.failsafeBrakingEnabled;
      }
      /**
       * This setting allows you to choose whether motor will forcibly stop once it enters a **FAILSAFE** state.
       *
       * *   A setting of FALSE will simply stop applying power to the motor, allowing it to spin down naturally.
       * *   A setting of TRUE will apply braking up to the `failsafeCurrentLimit`, actively stopping the motor
       *
       *
       * For more information about `failsafeBrakingEnabled`, visit our [MotorPositionController API Guide](https://www.phidgets.com/docs/MotorPositionController_API_Guide#Failsafe_Braking_Enabled)
       * @throws `PhidgetError`
       * @param failsafeBrakingEnabled - Enables failsafe braking
       */
      async setFailsafeBrakingEnabled(failsafeBrakingEnabled) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: failsafeBrakingEnabled ? 1 : 0
        });
        await bp.send(this._ch, 193);
      }
      /**
       * When the controller enters a **FAILSAFE** state, the controller will limit the current through the motor to the `failsafeCurrentLimit` value.
       *
       *
       * For more information about `failsafeCurrentLimit`, visit our [MotorPositionController API Guide](https://www.phidgets.com/docs/MotorPositionController_API_Guide#Failsafe_Current_Limit)
       * @returns The failsafe current limit value
       * @throws `PhidgetError`
       */
      getFailsafeCurrentLimit() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 281:
          case 288:
          case 304:
          case 311:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.failsafeCurrentLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.failsafeCurrentLimit;
      }
      /**
       * When the controller enters a **FAILSAFE** state, the controller will limit the current through the motor to the `failsafeCurrentLimit` value.
       *
       *
       * For more information about `failsafeCurrentLimit`, visit our [MotorPositionController API Guide](https://www.phidgets.com/docs/MotorPositionController_API_Guide#Failsafe_Current_Limit)
       * @throws `PhidgetError`
       * @param failsafeCurrentLimit - The failsafe current limit value
       */
      async setFailsafeCurrentLimit(failsafeCurrentLimit) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: failsafeCurrentLimit
        });
        await bp.send(this._ch, 192);
      }
      /**
       * The minimum value that `failsafeTime` can be set to when calling `enableFailsafe()`.
       * @returns The failsafe time
       * @throws `PhidgetError`
       */
      getMinFailsafeTime() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 255:
          case 264:
          case 270:
          case 292:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.minFailsafeTime === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minFailsafeTime;
      }
      /**
       * The maximum value that `failsafeTime` can be set to when calling `enableFailsafe()`.
       * @returns The failsafe time
       * @throws `PhidgetError`
       */
      getMaxFailsafeTime() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 255:
          case 264:
          case 270:
          case 292:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.maxFailsafeTime === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxFailsafeTime;
      }
      /**
       * The `fanMode` dictates the operating condition of the fan.
       *
       * *   Choose between on, off, or automatic (based on temperature).
       * *   If the `fanMode` is set to automatic, the fan will turn on when the temperature reaches 70°C and it will remain on until the temperature falls below 55°C.
       * *   If the `fanMode` is off, the controller will still turn on the fan if the temperature reaches 85°C and it will remain on until it falls below 70°C.
       * @returns The fan mode
       * @throws `PhidgetError`
       */
      getFanMode() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 255:
          case 261:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.fanMode === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.fanMode;
      }
      /**
       * The `fanMode` dictates the operating condition of the fan.
       *
       * *   Choose between on, off, or automatic (based on temperature).
       * *   If the `fanMode` is set to automatic, the fan will turn on when the temperature reaches 70°C and it will remain on until the temperature falls below 55°C.
       * *   If the `fanMode` is off, the controller will still turn on the fan if the temperature reaches 85°C and it will remain on until it falls below 70°C.
       * @throws `PhidgetError`
       * @param fanMode - The fan mode
       */
      async setFanMode(fanMode) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: fanMode
        });
        await bp.send(this._ch, 58);
      }
      /**
       * The controller will attempt to measure the inductance of your motor when opened. This value is used to improve control of the motor.
       *
       * *   Set this value during the `Phidget.Attach` event to skip motor characterization (including the audible beeps). You can use a previously saved `inductance` value, or information from your motor's datasheet.
       *
       *
       * For more information about `inductance`, visit our [MotorPositionController API Guide](https://www.phidgets.com/docs/MotorPositionController_API_Guide#Motor_Inductance)
       * @returns The inductance of your motor
       * @throws `PhidgetError`
       */
      getInductance() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 281:
          case 288:
          case 304:
          case 311:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.inductance === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.inductance;
      }
      /**
       * The controller will attempt to measure the inductance of your motor when opened. This value is used to improve control of the motor.
       *
       * *   Set this value during the `Phidget.Attach` event to skip motor characterization (including the audible beeps). You can use a previously saved `inductance` value, or information from your motor's datasheet.
       *
       *
       * For more information about `inductance`, visit our [MotorPositionController API Guide](https://www.phidgets.com/docs/MotorPositionController_API_Guide#Motor_Inductance)
       * @throws `PhidgetError`
       * @param inductance - The inductance of your motor
       */
      async setInductance(inductance) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: inductance
        });
        await bp.send(this._ch, 184);
      }
      /**
       * The minimum value that `inductance` can be set to. See `inductance` for details.
       * @returns The motor inductance value
       * @throws `PhidgetError`
       */
      getMinInductance() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 281:
          case 288:
          case 304:
          case 311:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.minInductance === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minInductance;
      }
      /**
       * The maximum value that `inductance` can be set to. See `inductance` for details.
       * @returns The motor inductance value
       * @throws `PhidgetError`
       */
      getMaxInductance() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 281:
          case 288:
          case 304:
          case 311:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.maxInductance === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxInductance;
      }
      /**
       * The encoder interface mode. Match the mode to the type of encoder you have attached.
       *
       * *   It is recommended to only change this when the encoder disabled in order to avoid unexpected results.
       * @returns The IO mode value.
       * @throws `PhidgetError`
       */
      getIOMode() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 255:
          case 261:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.IOMode === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.IOMode;
      }
      /**
       * The encoder interface mode. Match the mode to the type of encoder you have attached.
       *
       * *   It is recommended to only change this when the encoder disabled in order to avoid unexpected results.
       * @throws `PhidgetError`
       * @param IOMode - The IO mode value.
       */
      async setIOMode(IOMode) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: IOMode
        });
        await bp.send(this._ch, 65);
      }
      /**
       * Set this parameter to TRUE to adjust PID math to standardized units.
       * @returns Set this parameter to TRUE to adjust PID math to standardized units.
       * @throws `PhidgetError`
       */
      getNormalizePID() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 281:
          case 288:
          case 304:
          case 311:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.normalizePID === 2) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return !!this.data.normalizePID;
      }
      /**
       * Change the units of your parameters so that your application is more intuitive.
       *
       * *   Units for `position`, `targetPosition`, `velocityLimit`, `acceleration`, and `deadBand` can be set by the user through the `rescaleFactor`. The `rescaleFactor` allows you to use more intuitive units such as rotations, or degrees.
       *
       *
       * For more information about `rescaleFactor`, visit our [MotorPositionController API Guide](https://www.phidgets.com/docs/MotorPositionController_API_Guide#Rescale_Factor)
       * @returns The rescale factor value
       * @throws `PhidgetError`
       */
      getRescaleFactor() {
        this._assertOpen();
        if (this.data.rescaleFactor === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.rescaleFactor;
      }
      /**
       * Resets the failsafe timer, if one has been set. See `enableFailsafe()` for details.
       *
       * This function will fail if no failsafe timer has been set for the channel.
       * @throws `PhidgetError`
       */
      async resetFailsafe() {
        this._assertOpen();
        const bp = new BridgePacket();
        await bp.send(this._ch, 147);
      }
      /**
       * The `surgeCurrentLimit` allows for increased performance from your motor. The controller will limit the current through your motor to the `surgeCurrentLimit` briefly, then scale current down to the `currentLimit`.
       *
       * *   View `activeCurrentLimit` for information about what current limit the controller is actively following.
       *
       *
       * For more information about `surgeCurrentLimit`, visit our [MotorPositionController API Guide](https://www.phidgets.com/docs/MotorPositionController_API_Guide#Surge_Current_Limit)
       * @returns The surge current limit value
       * @throws `PhidgetError`
       */
      getSurgeCurrentLimit() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 281:
          case 288:
          case 304:
          case 311:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.surgeCurrentLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.surgeCurrentLimit;
      }
      /**
       * The `surgeCurrentLimit` allows for increased performance from your motor. The controller will limit the current through your motor to the `surgeCurrentLimit` briefly, then scale current down to the `currentLimit`.
       *
       * *   View `activeCurrentLimit` for information about what current limit the controller is actively following.
       *
       *
       * For more information about `surgeCurrentLimit`, visit our [MotorPositionController API Guide](https://www.phidgets.com/docs/MotorPositionController_API_Guide#Surge_Current_Limit)
       * @throws `PhidgetError`
       * @param surgeCurrentLimit - The surge current limit value
       */
      async setSurgeCurrentLimit(surgeCurrentLimit) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: surgeCurrentLimit
        });
        await bp.send(this._ch, 194);
      }
      /**
       * The minimum value that `surgeCurrentLimit` can be set to.
       * @returns The surge current value
       * @throws `PhidgetError`
       */
      getMinSurgeCurrentLimit() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 281:
          case 288:
          case 304:
          case 311:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.minSurgeCurrentLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minSurgeCurrentLimit;
      }
      /**
       * The maximum value that `surgeCurrentLimit` can be set to.
       * @returns The surge current value
       * @throws `PhidgetError`
       */
      getMaxSurgeCurrentLimit() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 281:
          case 288:
          case 304:
          case 311:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.maxSurgeCurrentLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxSurgeCurrentLimit;
      }
    }

    const OLD_KP_VELOCITY_SCALER = 2097151;
    /** @public */
    class MotorPositionController extends MotorPositionControllerBase {
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 29:
            this.data.position = bp.getNumber(0);
            if (this._isAttachedDone && this.onPositionChange) {
              try {
                this.onPositionChange((this.data.position + this.data.positionOffset) * this.data.rescaleFactor);
              } catch (err) {
                logEventException(err);
              }
            }
            break;
          case 10:
            if (bp.entryCount > 1) this.data.dataInterval = bp.getNumber(1);else this.data.dataInterval = bp.getNumber(0);
            this._FIREPropertyChange("DataInterval");
            this._FIREPropertyChange("DataRate");
            break;
          case 196:
            this.data.currentLimit = bp.getNumber(0);
            this._FIREPropertyChange("CurrentLimit");
            break;
          case 185:
            this.data.inductance = bp.getNumber(0);
            this._FIREPropertyChange("Inductance");
            break;
          case 195:
            this.data.surgeCurrentLimit = bp.getNumber(0);
            this._FIREPropertyChange("SurgeCurrentLimit");
            break;
          case 197:
            {
              const activeCurrentLimit = bp.getNumber(0);
              if (this.data.activeCurrentLimit != activeCurrentLimit) {
                this.data.activeCurrentLimit = activeCurrentLimit;
                this._FIREPropertyChange("ActiveCurrentLimit");
              }
              break;
            }
          case 188:
            {
              this.data.expectedPosition = bp.getNumber(0);
              if (this._isAttachedDone && this.onExpectedPositionChange) {
                try {
                  this.onExpectedPositionChange((this.data.expectedPosition + this.data.positionOffset) * this.data.rescaleFactor);
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          default:
            super._bridgeInput(bp);
            break;
        }
      }
      /** @internal */
      async _setDefaults() {
        try {
          await super._setDefaults();
        } catch (err) {
          if (err instanceof PhidgetError) {
            switch (err.errorCode) {
              case exports.ErrorCode.FAILSAFE:
                err.message = "External stop procedure initiated.";
                break;
              case exports.ErrorCode.BAD_POWER:
                err.message = "Your power supply voltage is too high for the motor controller to begin operation.";
                break;
              case exports.ErrorCode.POWER_CYCLE:
                err.message = "An overvoltage fault has triggered. Power your device off and on to resume operation. We recommend a PowerGuard Phidget to prevent this in future.";
                break;
              case exports.ErrorCode.HALLSENSOR:
                err.message = "The hall sensor of your BLDC motor is not reporting a valid input. The cable is likely damaged or unplugged.";
                break;
              case exports.ErrorCode.BADCURRENT:
                err.message = "The current sensor is seeing an unacceptable offset in its readings. Move the controller away from magnetic fields and try again.";
                break;
            }
          }
          throw err;
        }
      }
      /** @internal */
      _errorHandler(code) {
        switch (code) {
          case exports.ErrorEventCode.MOTOR_STALL_CONDITION:
            this.data.engaged = 0;
            break;
        }
      }
      getAcceleration() {
        this._assertOpen();
        if (this.data.acceleration === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.acceleration * Math.abs(this.data.rescaleFactor);
      }
      async setAcceleration(acceleration) {
        this._assertOpen();
        const calcAccel = acceleration / Math.abs(this.data.rescaleFactor);
        if (calcAccel < this.data.minAcceleration || calcAccel > this.data.maxAcceleration) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Value must be in range: " + this.minAcceleration + " - " + this.maxAcceleration + ".");
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: calcAccel
        });
        await bp.send(this._ch, 40);
      }
      getMinAcceleration() {
        this._assertOpen();
        if (this.data.minAcceleration === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minAcceleration * Math.abs(this.data.rescaleFactor);
      }
      getMaxAcceleration() {
        this._assertOpen();
        if (this.data.maxAcceleration === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxAcceleration * Math.abs(this.data.rescaleFactor);
      }
      addPositionOffset(positionOffset) {
        this._assertOpen();
        this.data.positionOffset += positionOffset / this.data.rescaleFactor;
      }
      getDeadBand() {
        this._assertOpen();
        if (this.data.deadBand === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.deadBand * Math.abs(this.data.rescaleFactor);
      }
      async setDeadBand(deadBand) {
        this._assertOpen();
        const calcDeadband = deadBand / Math.abs(this.data.rescaleFactor);
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: calcDeadband
        });
        await bp.send(this._ch, 120);
      }
      getPosition() {
        this._assertOpen();
        if (this.data.position === 9223372036854776000) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return (this.data.position + this.data.positionOffset) * this.data.rescaleFactor;
      }
      getMinPosition() {
        this._assertOpen();
        if (this.data.minPosition === 9223372036854776000) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return (this.data.minPosition + this.data.positionOffset) * Math.abs(this.data.rescaleFactor);
      }
      getMaxPosition() {
        this._assertOpen();
        if (this.data.maxPosition === 9223372036854776000) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return (this.data.maxPosition + this.data.positionOffset) * Math.abs(this.data.rescaleFactor);
      }
      setRescaleFactor(rescaleFactor) {
        this._assertOpen();
        this.data.rescaleFactor = rescaleFactor;
      }
      getTargetPosition() {
        this._assertOpen();
        if (this.data.targetPosition === 9223372036854776000) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return (this.data.targetPosition + this.data.positionOffset) * this.data.rescaleFactor;
      }
      async setTargetPosition(targetPosition) {
        this._assertOpen();
        const calcPosition = targetPosition / this.data.rescaleFactor - this.data.positionOffset;
        if (calcPosition < this.data.minPosition || calcPosition > this.data.maxPosition) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Value must be in range: " + this.minPosition + " - " + this.maxPosition + ".");
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "l",
          value: calcPosition
        });
        await bp.send(this._ch, 83);
      }
      getVelocityLimit() {
        this._assertOpen();
        if (this.data.velocityLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.velocityLimit * Math.abs(this.data.rescaleFactor);
      }
      getStallVelocity() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 292:
          case 295:
          case 298:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.stallVelocity === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.stallVelocity * Math.abs(this.data.rescaleFactor);
      }
      async setStallVelocity(stallVelocity) {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 292:
          case 295:
          case 298:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        const calcVelocity = stallVelocity / Math.abs(this.data.rescaleFactor);
        if (calcVelocity < this.data.minStallVelocity || calcVelocity > this.data.maxStallVelocity) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Value must be in range: " + this.minStallVelocity + " - " + this.maxStallVelocity + ".");
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: calcVelocity
        });
        await bp.send(this._ch, 141);
      }
      async setVelocityLimit(velocityLimit) {
        this._assertOpen();
        const calcLimit = velocityLimit / Math.abs(this.data.rescaleFactor);
        if (calcLimit < this.data.minVelocityLimit || calcLimit > this.data.maxVelocityLimit) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Value must be in range: " + this.minVelocityLimit + " - " + this.maxVelocityLimit + ".");
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: calcLimit
        });
        await bp.send(this._ch, 55);
      }
      getMinStallVelocity() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 292:
          case 295:
          case 298:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.minStallVelocity === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minStallVelocity * Math.abs(this.data.rescaleFactor);
      }
      getMaxStallVelocity() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 292:
          case 295:
          case 298:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.maxStallVelocity === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxStallVelocity * Math.abs(this.data.rescaleFactor);
      }
      getMinVelocityLimit() {
        this._assertOpen();
        if (this.data.minVelocityLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minVelocityLimit * Math.abs(this.data.rescaleFactor);
      }
      getMaxVelocityLimit() {
        this._assertOpen();
        if (this.data.maxVelocityLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxVelocityLimit * Math.abs(this.data.rescaleFactor);
      }
      getKd() {
        this._assertOpen();
        if (this.data.kd === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        switch (this._ch?.chDef.uid) {
          case 281:
          case 288:
          case 304:
          case 311:
            return this.data.kd / Math.abs(this.data.rescaleFactor);
          default:
            if (this.data.normalizePID) return this.data.kd / (OLD_KP_VELOCITY_SCALER * 1000.0) / Math.abs(this.data.rescaleFactor);
            return this.data.kd;
        }
      }
      async setKd(kd) {
        this._assertOpen();
        const bp = new BridgePacket();
        switch (this._ch?.chDef.uid) {
          case 281:
          case 288:
          case 304:
          case 311:
            bp.set({
              name: "0",
              type: "g",
              value: kd * Math.abs(this.data.rescaleFactor)
            });
            break;
          default:
            if (this.data.normalizePID) bp.set({
              name: "0",
              type: "g",
              value: kd * (OLD_KP_VELOCITY_SCALER * 1000.0) * Math.abs(this.data.rescaleFactor)
            });else bp.set({
              name: "0",
              type: "g",
              value: kd
            });
            break;
        }
        await bp.send(this._ch, 136);
      }
      getKi() {
        this._assertOpen();
        if (this.data.ki === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        switch (this._ch?.chDef.uid) {
          case 281:
          case 288:
          case 304:
          case 311:
            return this.data.ki / Math.abs(this.data.rescaleFactor);
          default:
            if (this.data.normalizePID) return this.data.ki / (OLD_KP_VELOCITY_SCALER / 1000.0) / Math.abs(this.data.rescaleFactor);
            return this.data.ki;
        }
      }
      async setKi(ki) {
        this._assertOpen();
        const bp = new BridgePacket();
        switch (this._ch?.chDef.uid) {
          case 281:
          case 288:
          case 304:
          case 311:
            bp.set({
              name: "0",
              type: "g",
              value: ki * Math.abs(this.data.rescaleFactor)
            });
            break;
          default:
            if (this.data.normalizePID) bp.set({
              name: "0",
              type: "g",
              value: ki * (OLD_KP_VELOCITY_SCALER / 1000.0) * Math.abs(this.data.rescaleFactor)
            });else bp.set({
              name: "0",
              type: "g",
              value: ki
            });
            break;
        }
        await bp.send(this._ch, 142);
      }
      getKp() {
        this._assertOpen();
        if (this.data.kp === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        switch (this._ch?.chDef.uid) {
          case 281:
          case 288:
          case 304:
          case 311:
            return this.data.kp / Math.abs(this.data.rescaleFactor);
          default:
            if (this.data.normalizePID) return this.data.kp / OLD_KP_VELOCITY_SCALER / Math.abs(this.data.rescaleFactor);
            return this.data.kp;
        }
      }
      async setKp(kp) {
        this._assertOpen();
        const bp = new BridgePacket();
        switch (this._ch?.chDef.uid) {
          case 281:
          case 288:
          case 304:
          case 311:
            bp.set({
              name: "0",
              type: "g",
              value: kp * Math.abs(this.data.rescaleFactor)
            });
            break;
          default:
            if (this.data.normalizePID) bp.set({
              name: "0",
              type: "g",
              value: kp * OLD_KP_VELOCITY_SCALER * Math.abs(this.data.rescaleFactor)
            });else bp.set({
              name: "0",
              type: "g",
              value: kp
            });
            break;
        }
        await bp.send(this._ch, 135);
      }
      getExpectedPosition() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 281:
          case 288:
          case 304:
          case 311:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.expectedPosition === 9223372036854776000) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return (this.data.expectedPosition + this.data.positionOffset) * this.data.rescaleFactor;
      }
      setNormalizePID(normalizePID) {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 255:
          case 261:
          case 264:
          case 267:
          case 270:
          case 273:
          case 292:
          case 295:
          case 298:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        this.data.normalizePID = normalizePID ? 1 : 0;
      }
      getPositionType() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 304:
          case 311:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.positionType === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.positionType;
      }
      async setPositionType(positionType) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: positionType
        });
        await bp.send(this._ch, 187);
        switch (this._ch?.chDef.uid) {
          case 304:
          case 311:
            switch (positionType) {
              case exports.PositionType.ENCODER:
                this.data.maxVelocityLimit = 500000;
                break;
              case exports.PositionType.HALL_SENSOR:
                this.data.maxVelocityLimit = 2000;
                break;
            }
            break;
        }
      }
    }

    /**
     * The Motor Velocity Controller class controls the velocity and acceleration of the attached motor. It also contains various other control and monitoring functions that aid in the control of the motor.
     * @public
     */
    class MotorVelocityControllerBase extends PhidgetChannel {
      /** @internal */
      data;
      onVelocityChange = null;
      /** @internal */
      _gotVelocityChangeErrorEvent;
      onDutyCycleUpdate = null;
      /** @internal */
      _gotDutyCycleUpdateErrorEvent;
      onExpectedVelocityChange = null;
      /** @internal */
      _gotExpectedVelocityChangeErrorEvent;
      constructor(ch) {
        super(ch);
        this._class = exports.ChannelClass.MOTOR_VELOCITY_CONTROLLER;
        this.name = "MotorVelocityController";
        this.data = this._initData();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 40:
            this.data.acceleration = bp.entries[0].v;
            this._FIREPropertyChange('Acceleration', bp);
            break;
          case 51:
            this.data.currentLimit = bp.entries[0].v;
            this._FIREPropertyChange('CurrentLimit', bp);
            break;
          case 54:
            if (bp.entryCount > 1) this.data.dataInterval = bp.entries[1].v;else this.data.dataInterval = bp.entries[0].v;
            this._FIREPropertyChange('DataInterval', bp);
            this._FIREPropertyChange('DataRate', bp);
            break;
          case 120:
            this.data.deadBand = bp.entries[0].v;
            this._FIREPropertyChange('DeadBand', bp);
            break;
          case 57:
            this.data.engaged = bp.entries[0].v;
            this._FIREPropertyChange('Engaged', bp);
            break;
          case 191:
            this.data.enableExpectedVelocity = bp.entries[0].v;
            this._FIREPropertyChange('EnableExpectedVelocity', bp);
            break;
          case 146:
            break;
          case 193:
            this.data.failsafeBrakingEnabled = bp.entries[0].v;
            this._FIREPropertyChange('FailsafeBrakingEnabled', bp);
            break;
          case 192:
            this.data.failsafeCurrentLimit = bp.entries[0].v;
            this._FIREPropertyChange('FailsafeCurrentLimit', bp);
            break;
          case 184:
            this.data.inductance = bp.entries[0].v;
            this._FIREPropertyChange('Inductance', bp);
            break;
          case 136:
            this.data.kd = bp.entries[0].v;
            this._FIREPropertyChange('Kd', bp);
            break;
          case 142:
            this.data.ki = bp.entries[0].v;
            this._FIREPropertyChange('Ki', bp);
            break;
          case 135:
            this.data.kp = bp.entries[0].v;
            this._FIREPropertyChange('Kp', bp);
            break;
          case 187:
            this.data.positionType = bp.entries[0].v;
            this._FIREPropertyChange('PositionType', bp);
            break;
          case 147:
            break;
          case 141:
            this.data.stallVelocity = bp.entries[0].v;
            this._FIREPropertyChange('StallVelocity', bp);
            break;
          case 194:
            this.data.surgeCurrentLimit = bp.entries[0].v;
            this._FIREPropertyChange('SurgeCurrentLimit', bp);
            break;
          case 55:
            this.data.targetVelocity = bp.entries[0].v;
            this._FIREPropertyChange('TargetVelocity', bp);
            break;
          case 16:
            {
              this.data.dutyCycle = bp.entries[0].v;
              if (this._isAttachedDone && this.onDutyCycleUpdate) {
                try {
                  this.onDutyCycleUpdate(this.data.dutyCycle);
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          default:
            throw new PhidgetError(exports.ErrorCode.INVALID_PACKET, "Unsupported bridge packet: 0x" + bp.vpkt.toString(16));
        }
      }
      /** @internal */
      _initData() {
        return {
          dataInterval: 1e+300,
          minDataInterval: 4294967295,
          maxDataInterval: 4294967295,
          minDataRate: 1e+300,
          maxDataRate: 1e+300,
          currentLimit: 1e+300,
          maxCurrentLimit: 1e+300,
          minCurrentLimit: 1e+300,
          surgeCurrentLimit: 1e+300,
          maxSurgeCurrentLimit: 1e+300,
          minSurgeCurrentLimit: 1e+300,
          activeCurrentLimit: 1e+300,
          dutyCycle: 1e+300,
          engaged: 2,
          targetVelocity: 1e+300,
          minTargetVelocity: 1e+300,
          maxTargetVelocity: 1e+300,
          velocity: 1e+300,
          enableExpectedVelocity: 2,
          expectedVelocity: 1e+300,
          maxAcceleration: 1e+300,
          minAcceleration: 1e+300,
          acceleration: 1e+300,
          rescaleFactor: 1e+300,
          kp: 1e+300,
          kd: 1e+300,
          ki: 1e+300,
          stallVelocity: 1e+300,
          minStallVelocity: 1e+300,
          maxStallVelocity: 1e+300,
          maxFailsafeTime: 4294967295,
          minFailsafeTime: 4294967295,
          inductance: 1e+300,
          maxInductance: 1e+300,
          minInductance: 1e+300,
          positionType: 2147483647,
          deadBand: 1e+300,
          failsafeCurrentLimit: 1e+300,
          failsafeBrakingEnabled: 2
        };
      }
      /** @internal */
      _initAfterOpen() {}
      /** @internal */
      async _setDefaults() {}
      /** @internal */
      _hasInitialState() {
        return true;
      }
      /** @internal */
      _fireInitialEvents() {}
      /**
       * The rate at which the controller can change the motor's velocity.
       *
       * *   Use the `rescaleFactor` to convert the units of this property to more intuitive units, such as rotations or degrees.
       *
       *
       * For more information about `acceleration`, visit our [MotorVelocityController API Guide](https://www.phidgets.com/docs/MotorVelocityController_API_Guide#Acceleration)
       * @throws `PhidgetError`
       */
      get acceleration() {
        return this.getAcceleration();
      }
      /**
       * The minimum value that `acceleration` can be set to.
       *
       * *   Use the `rescaleFactor` to convert the units of this property to more intuitive units, such as rotations or degrees.
       * @throws `PhidgetError`
       */
      get minAcceleration() {
        return this.getMinAcceleration();
      }
      /**
       * The maximum value that `acceleration` can be set to.
       *
       * *   Use the `rescaleFactor` to convert the units of this property to more intuitive units, such as rotations or degrees.
       * @throws `PhidgetError`
       */
      get maxAcceleration() {
        return this.getMaxAcceleration();
      }
      /**
       * The current limit that the controller is actively following. The `surgeCurrentLimit`, `currentLimit`, and temperature will impact this value.
       * @throws `PhidgetError`
       */
      get activeCurrentLimit() {
        return this.getActiveCurrentLimit();
      }
      /**
       * The controller will limit the current through the motor to the `currentLimit` value.
       *
       * *   View `activeCurrentLimit` for information about what current limit the controller is actively following.
       *
       *
       * For more information about `currentLimit`, visit our [MotorVelocityController API Guide](https://www.phidgets.com/docs/MotorVelocityController_API_Guide#Current_Limit)
       * @throws `PhidgetError`
       */
      get currentLimit() {
        return this.getCurrentLimit();
      }
      /**
       * The minimum current limit that can be set for the device.
       * @throws `PhidgetError`
       */
      get minCurrentLimit() {
        return this.getMinCurrentLimit();
      }
      /**
       * The maximum current limit that can be set for the device.
       * @throws `PhidgetError`
       */
      get maxCurrentLimit() {
        return this.getMaxCurrentLimit();
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `VelocityChange` / `DutyCycleUpdate` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * @throws `PhidgetError`
       */
      get dataInterval() {
        return this.getDataInterval();
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get minDataInterval() {
        return this.getMinDataInterval();
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataInterval() {
        return this.getMaxDataInterval();
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       */
      get dataRate() {
        return this.getDataRate();
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get minDataRate() {
        return this.getMinDataRate();
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataRate() {
        return this.getMaxDataRate();
      }
      /**
       * This parameter specifies a minimum `velocity` below which your system will relax if the `targetVelocity` is set to 0, to prevent unwanted jitter.
       *
       * *   Use the `rescaleFactor` to convert the units of this property to more intuitive units, such as rotations or degrees.
       *
       *
       * For more information about `deadBand`, visit our [MotorVelocityController API Guide](https://www.phidgets.com/docs/MotorVelocityController_API_Guide#Deadband)
       * @throws `PhidgetError`
       */
      get deadBand() {
        return this.getDeadBand();
      }
      /**
       * The most recent `dutyCycle` value that the controller has reported.
       *
       * *   This value will be between -1 and 1 where a sign change (±) is indicitave of a direction change.
       * *   `dutyCycle` is an indication of the average voltage across the motor. At a constant load, an increase in `dutyCycle` indicates an increase in motor speed.
       *
       *
       * For more information about `dutyCycle`, visit our [MotorVelocityController API Guide](https://www.phidgets.com/docs/MotorVelocityController_API_Guide#Duty_Cycle)
       * @throws `PhidgetError`
       */
      get dutyCycle() {
        return this.getDutyCycle();
      }
      /**
       * When engaged, the controller has the ability to be controlled. When disengaged, the controller will stop powering to your motor, it will instead be in a freewheel state.
       *
       *
       * For more information about `engaged`, visit our [MotorVelocityController API Guide](https://www.phidgets.com/docs/MotorVelocityController_API_Guide#Engage_Motor)
       * @throws `PhidgetError`
       */
      get engaged() {
        return this.getEngaged();
      }
      /**
       * This controller uses trapezoidal motion profiling combined with a PID loop to accurately track velocity. The `expectedVelocity` represents the current velocity the controller is tracking along the trapezoidal motion curve. The error of your PID loop is calculated by taking the difference of `velocity` and `expectedVelocity`. You can use this value to verify your controller is working as expected.
       *
       * *   Set `enableExpectedVelocity` to **TRUE** to enable the change event for this property.
       * *   Use the `rescaleFactor` to convert the units of this property to more intuitive units, such as rotations or degrees.
       * @throws `PhidgetError`
       */
      get expectedVelocity() {
        return this.getExpectedVelocity();
      }
      /**
       * When enabled, the `expectedVelocity` will be sent back from the controller.
       * @throws `PhidgetError`
       */
      get enableExpectedVelocity() {
        return this.getEnableExpectedVelocity();
      }
      /**
       * This setting allows you to choose whether motor will forcibly stop once it enters a **FAILSAFE** state.
       *
       * *   A setting of FALSE will simply stop applying power to the motor, allowing it to spin down naturally.
       * *   A setting of TRUE will apply braking up to the `failsafeCurrentLimit`, actively stopping the motor
       *
       *
       * For more information about `failsafeBrakingEnabled`, visit our [MotorVelocityController API Guide](https://www.phidgets.com/docs/MotorVelocityController_API_Guide#Failsafe_Braking_Enabled)
       * @throws `PhidgetError`
       */
      get failsafeBrakingEnabled() {
        return this.getFailsafeBrakingEnabled();
      }
      /**
       * When the controller enters a **FAILSAFE** state, the controller will limit the current through the motor to the `failsafeCurrentLimit` value.
       *
       *
       * For more information about `failsafeCurrentLimit`, visit our [MotorVelocityController API Guide](https://www.phidgets.com/docs/MotorVelocityController_API_Guide#Failsafe_Current_Limit)
       * @throws `PhidgetError`
       */
      get failsafeCurrentLimit() {
        return this.getFailsafeCurrentLimit();
      }
      /**
       * The minimum value that `failsafeTime` can be set to when calling `enableFailsafe()`.
       * @throws `PhidgetError`
       */
      get minFailsafeTime() {
        return this.getMinFailsafeTime();
      }
      /**
       * The maximum value that `failsafeTime` can be set to when calling `enableFailsafe()`.
       * @throws `PhidgetError`
       */
      get maxFailsafeTime() {
        return this.getMaxFailsafeTime();
      }
      /**
       * The controller will attempt to measure the inductance of your motor when opened. This value is used to improve control of the motor.
       *
       * *   Set this value during the `Phidget.Attach` event to skip motor characterization (including the audible beeps). You can use a previously saved `inductance` value, or information from your motor's datasheet.
       *
       *
       * For more information about `inductance`, visit our [MotorVelocityController API Guide](https://www.phidgets.com/docs/MotorVelocityController_API_Guide#Motor_Inductance)
       * @throws `PhidgetError`
       */
      get inductance() {
        return this.getInductance();
      }
      /**
       * The minimum value that `inductance` can be set to. See `inductance` for details.
       * @throws `PhidgetError`
       */
      get minInductance() {
        return this.getMinInductance();
      }
      /**
       * The maximum value that `inductance` can be set to. See `inductance` for details.
       * @throws `PhidgetError`
       */
      get maxInductance() {
        return this.getMaxInductance();
      }
      /**
       * Derivative gain constant. A higher `kd` will help reduce oscillations.
       *
       *
       * For more information about `kd`, visit our [MotorVelocityController API Guide](https://www.phidgets.com/docs/MotorVelocityController_API_Guide#Tunings_Constants_\(Kp,_Ki,_Kd\))
       * @throws `PhidgetError`
       */
      get kd() {
        return this.getKd();
      }
      /**
       * Integral gain constant. The integral term will help eliminate steady-state error.
       *
       *
       * For more information about `ki`, visit our [MotorVelocityController API Guide](https://www.phidgets.com/docs/MotorVelocityController_API_Guide#Tunings_Constants_\(Kp,_Ki,_Kd\))
       * @throws `PhidgetError`
       */
      get ki() {
        return this.getKi();
      }
      /**
       * Proportional gain constant. A small `kp` value will result in a less responsive controller, however, if `kp` is too high, the system can become unstable.
       *
       *
       * For more information about `kp`, visit our [MotorVelocityController API Guide](https://www.phidgets.com/docs/MotorVelocityController_API_Guide#Tunings_Constants_\(Kp,_Ki,_Kd\))
       * @throws `PhidgetError`
       */
      get kp() {
        return this.getKp();
      }
      /**
       * Determines whether the controller uses the hall effect sensors or an encoder for velocity information. This setting is locked in once the channel is `engaged` and cannot be changed until the channel is reset.
       * @throws `PhidgetError`
       */
      get positionType() {
        return this.getPositionType();
      }
      /**
       * Change the units of your parameters so that your application is more intuitive.
       *
       * *   Units for `acceleration`, `deadBand`, `expectedVelocity`, `targetVelocity`, and `velocity` can be set by the user through the `rescaleFactor`. The `rescaleFactor` allows you to use more intuitive units such as rotations, or degrees.
       *
       *
       * For more information about `rescaleFactor`, visit our [MotorVelocityController API Guide](https://www.phidgets.com/docs/MotorVelocityController_API_Guide#Rescale_Factor)
       * @throws `PhidgetError`
       */
      get rescaleFactor() {
        return this.getRescaleFactor();
      }
      set rescaleFactor(rescaleFactor) {
        this.setRescaleFactor(rescaleFactor);
      }
      /**
       * Before reading this description, it is important to note the difference between the units of `stallVelocity` and `dutyCycle`.
       *
       * *   `dutyCycle` is a number between -1 and 1 with units of 'duty cycle'. It simply represents the average voltage across the motor.
       * *   `stallVelocity` represents a real velocity (e.g. m/s, RPM, etc.) and the units are determined by the `rescaleFactor`. With a `rescaleFactor` of 1, the default units would be in commutations per second.
       *
       * If the load on your motor is large, your motor may begin rotating more slowly, or even fully stall. Depending on the voltage across your motor, this may result in a large amount of current through both the controller and the motor. In order to prevent damage in these situations, you can use the `stallVelocity` property.
       *
       * The `stallVelocity` should be set to the lowest velocity you would expect from your motor. The controller will then monitor the motor's velocity, as well as the `dutyCycle`, and prevent a 'dangerous stall' from occuring. If the controller detects a dangerous stall, it will immediately disengage the motor (i.e. `engaged` will be set to false) and an error will be reported to your program.
       *
       * *   A 'dangerous stall' will occur faster when the `dutyCycle` is higher (i.e. when the average voltage across the motor is higher)
       * *   A 'dangerous stall' will occur faster as (`stallVelocity` - motor velocity) becomes larger .
       *
       * Setting `stallVelocity` to 0 will turn off stall protection functionality.
       * @throws `PhidgetError`
       */
      get stallVelocity() {
        return this.getStallVelocity();
      }
      /**
       * The lower bound of `stallVelocity`.
       * @throws `PhidgetError`
       */
      get minStallVelocity() {
        return this.getMinStallVelocity();
      }
      /**
       * The upper bound of `stallVelocity`.
       * @throws `PhidgetError`
       */
      get maxStallVelocity() {
        return this.getMaxStallVelocity();
      }
      /**
       * The `surgeCurrentLimit` allows for increased performance from your motor. The controller will limit the current through your motor to the `surgeCurrentLimit` briefly, then scale current down to the `currentLimit`.
       *
       * *   View `activeCurrentLimit` for information about what current limit the controller is actively following.
       *
       *
       * For more information about `surgeCurrentLimit`, visit our [MotorVelocityController API Guide](https://www.phidgets.com/docs/MotorVelocityController_API_Guide#Surge_Current_Limit)
       * @throws `PhidgetError`
       */
      get surgeCurrentLimit() {
        return this.getSurgeCurrentLimit();
      }
      /**
       * The minimum value that `surgeCurrentLimit` can be set to.
       * @throws `PhidgetError`
       */
      get minSurgeCurrentLimit() {
        return this.getMinSurgeCurrentLimit();
      }
      /**
       * The maximum value that `surgeCurrentLimit` can be set to.
       * @throws `PhidgetError`
       */
      get maxSurgeCurrentLimit() {
        return this.getMaxSurgeCurrentLimit();
      }
      /**
       * When moving, the motor velocity will be limited by this value.
       *
       * *   Use the `rescaleFactor` to convert the units of this property to more intuitive units, such as rotations or degrees.
       *
       *
       * For more information about `targetVelocity`, visit our [MotorVelocityController API Guide](https://www.phidgets.com/docs/MotorVelocityController_API_Guide#Target_Velocity)
       * @throws `PhidgetError`
       */
      get targetVelocity() {
        return this.getTargetVelocity();
      }
      /**
       * The minimum value that `targetVelocity` can be set to.
       *
       * *   Use the `rescaleFactor` to convert the units of this property to more intuitive units, such as rotations or degrees.
       * @throws `PhidgetError`
       */
      get minTargetVelocity() {
        return this.getMinTargetVelocity();
      }
      /**
       * The maximum value that `targetVelocity` can be set to.
       *
       * *   Use the `rescaleFactor` to convert the units of this property to more intuitive units, such as rotations or degrees.
       * @throws `PhidgetError`
       */
      get maxTargetVelocity() {
        return this.getMaxTargetVelocity();
      }
      /**
       * The most recent velocity value that the controller has reported.
       *
       * *   Use the `rescaleFactor` to convert the units of this property to more intuitive units, such as rotations or degrees.
       * @throws `PhidgetError`
       */
      get velocity() {
        return this.getVelocity();
      }
      /**
       * The current limit that the controller is actively following. The `surgeCurrentLimit`, `currentLimit`, and temperature will impact this value.
       * @returns The active current limit value
       * @throws `PhidgetError`
       */
      getActiveCurrentLimit() {
        this._assertOpen();
        if (this.data.activeCurrentLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.activeCurrentLimit;
      }
      /**
       * The controller will limit the current through the motor to the `currentLimit` value.
       *
       * *   View `activeCurrentLimit` for information about what current limit the controller is actively following.
       *
       *
       * For more information about `currentLimit`, visit our [MotorVelocityController API Guide](https://www.phidgets.com/docs/MotorVelocityController_API_Guide#Current_Limit)
       * @returns Motor current limit
       * @throws `PhidgetError`
       */
      getCurrentLimit() {
        this._assertOpen();
        if (this.data.currentLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.currentLimit;
      }
      /**
       * The controller will limit the current through the motor to the `currentLimit` value.
       *
       * *   View `activeCurrentLimit` for information about what current limit the controller is actively following.
       *
       *
       * For more information about `currentLimit`, visit our [MotorVelocityController API Guide](https://www.phidgets.com/docs/MotorVelocityController_API_Guide#Current_Limit)
       * @throws `PhidgetError`
       * @param currentLimit - Motor current limit
       */
      async setCurrentLimit(currentLimit) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: currentLimit
        });
        await bp.send(this._ch, 51);
      }
      /**
       * The minimum current limit that can be set for the device.
       * @returns Minimum current limit
       * @throws `PhidgetError`
       */
      getMinCurrentLimit() {
        this._assertOpen();
        if (this.data.minCurrentLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minCurrentLimit;
      }
      /**
       * The maximum current limit that can be set for the device.
       * @returns Maximum current limit
       * @throws `PhidgetError`
       */
      getMaxCurrentLimit() {
        this._assertOpen();
        if (this.data.maxCurrentLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxCurrentLimit;
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `VelocityChange` / `DutyCycleUpdate` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getDataInterval() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.dataInterval;
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `VelocityChange` / `DutyCycleUpdate` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * @throws `PhidgetError`
       * @param dataInterval - The data interval value
       */
      async setDataInterval(dataInterval) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: dataInterval
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMinDataInterval() {
        this._assertOpen();
        if (this.data.minDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataInterval;
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMaxDataInterval() {
        this._assertOpen();
        if (this.data.maxDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @returns The data rate for the channel
       * @throws `PhidgetError`
       */
      getDataRate() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return 1000.0 / this.data.dataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       * @param dataRate - The data rate for the channel
       */
      async setDataRate(dataRate) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: Math.round(1000.0 / dataRate)
        });
        bp.set({
          name: "1",
          type: "g",
          value: 1000.0 / dataRate
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMinDataRate() {
        this._assertOpen();
        if (this.data.minDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataRate;
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMaxDataRate() {
        this._assertOpen();
        if (this.data.maxDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataRate;
      }
      /**
       * The most recent `dutyCycle` value that the controller has reported.
       *
       * *   This value will be between -1 and 1 where a sign change (±) is indicitave of a direction change.
       * *   `dutyCycle` is an indication of the average voltage across the motor. At a constant load, an increase in `dutyCycle` indicates an increase in motor speed.
       *
       *
       * For more information about `dutyCycle`, visit our [MotorVelocityController API Guide](https://www.phidgets.com/docs/MotorVelocityController_API_Guide#Duty_Cycle)
       * @returns The duty cycle value.
       * @throws `PhidgetError`
       */
      getDutyCycle() {
        this._assertOpen();
        if (this.data.dutyCycle === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.dutyCycle;
      }
      /**
       * When engaged, the controller has the ability to be controlled. When disengaged, the controller will stop powering to your motor, it will instead be in a freewheel state.
       *
       *
       * For more information about `engaged`, visit our [MotorVelocityController API Guide](https://www.phidgets.com/docs/MotorVelocityController_API_Guide#Engage_Motor)
       * @returns The engaged value.
       * @throws `PhidgetError`
       */
      getEngaged() {
        this._assertOpen();
        if (this.data.engaged === 2) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return !!this.data.engaged;
      }
      /**
       * When engaged, the controller has the ability to be controlled. When disengaged, the controller will stop powering to your motor, it will instead be in a freewheel state.
       *
       *
       * For more information about `engaged`, visit our [MotorVelocityController API Guide](https://www.phidgets.com/docs/MotorVelocityController_API_Guide#Engage_Motor)
       * @throws `PhidgetError`
       * @param engaged - The engaged value.
       */
      async setEngaged(engaged) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: engaged ? 1 : 0
        });
        await bp.send(this._ch, 57);
      }
      /**
       * When enabled, the `expectedVelocity` will be sent back from the controller.
       * @throws `PhidgetError`
       * @param enableExpectedVelocity - Enable expected velocity feedback
       */
      async setEnableExpectedVelocity(enableExpectedVelocity) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: enableExpectedVelocity ? 1 : 0
        });
        await bp.send(this._ch, 191);
      }
      /**
       * When enabled, the `expectedVelocity` will be sent back from the controller.
       * @returns Enable expected velocity feedback
       * @throws `PhidgetError`
       */
      getEnableExpectedVelocity() {
        this._assertOpen();
        if (this.data.enableExpectedVelocity === 2) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return !!this.data.enableExpectedVelocity;
      }
      /**
       * Enables the **failsafe** feature for the channel, with the specified **failsafe time**.
       *
       * Enabling the failsafe feature starts a recurring **failsafe timer** for the channel. Once the failsafe is enabled, the timer must be reset within the specified time or the channel will enter a **failsafe state**. For Motor Velocity Controller channels, this will disengage the motor. The failsafe timer can be reset by using any API call **_except_** for the following:
       *
       * *   `setRescaleFactor()`
       * *   'get' API calls
       *
       * For more information about failsafe, visit our [Failsafe Guide](https://www.phidgets.com/docs/Failsafe_Guide).
       * @throws `PhidgetError`
       * @param failsafeTime - Failsafe timeout in milliseconds
       */
      async enableFailsafe(failsafeTime) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: failsafeTime
        });
        await bp.send(this._ch, 146);
      }
      /**
       * This setting allows you to choose whether motor will forcibly stop once it enters a **FAILSAFE** state.
       *
       * *   A setting of FALSE will simply stop applying power to the motor, allowing it to spin down naturally.
       * *   A setting of TRUE will apply braking up to the `failsafeCurrentLimit`, actively stopping the motor
       *
       *
       * For more information about `failsafeBrakingEnabled`, visit our [MotorVelocityController API Guide](https://www.phidgets.com/docs/MotorVelocityController_API_Guide#Failsafe_Braking_Enabled)
       * @returns Enables failsafe braking
       * @throws `PhidgetError`
       */
      getFailsafeBrakingEnabled() {
        this._assertOpen();
        if (this.data.failsafeBrakingEnabled === 2) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return !!this.data.failsafeBrakingEnabled;
      }
      /**
       * This setting allows you to choose whether motor will forcibly stop once it enters a **FAILSAFE** state.
       *
       * *   A setting of FALSE will simply stop applying power to the motor, allowing it to spin down naturally.
       * *   A setting of TRUE will apply braking up to the `failsafeCurrentLimit`, actively stopping the motor
       *
       *
       * For more information about `failsafeBrakingEnabled`, visit our [MotorVelocityController API Guide](https://www.phidgets.com/docs/MotorVelocityController_API_Guide#Failsafe_Braking_Enabled)
       * @throws `PhidgetError`
       * @param failsafeBrakingEnabled - Enables failsafe braking
       */
      async setFailsafeBrakingEnabled(failsafeBrakingEnabled) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: failsafeBrakingEnabled ? 1 : 0
        });
        await bp.send(this._ch, 193);
      }
      /**
       * When the controller enters a **FAILSAFE** state, the controller will limit the current through the motor to the `failsafeCurrentLimit` value.
       *
       *
       * For more information about `failsafeCurrentLimit`, visit our [MotorVelocityController API Guide](https://www.phidgets.com/docs/MotorVelocityController_API_Guide#Failsafe_Current_Limit)
       * @returns The failsafe current limit value
       * @throws `PhidgetError`
       */
      getFailsafeCurrentLimit() {
        this._assertOpen();
        if (this.data.failsafeCurrentLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.failsafeCurrentLimit;
      }
      /**
       * When the controller enters a **FAILSAFE** state, the controller will limit the current through the motor to the `failsafeCurrentLimit` value.
       *
       *
       * For more information about `failsafeCurrentLimit`, visit our [MotorVelocityController API Guide](https://www.phidgets.com/docs/MotorVelocityController_API_Guide#Failsafe_Current_Limit)
       * @throws `PhidgetError`
       * @param failsafeCurrentLimit - The failsafe current limit value
       */
      async setFailsafeCurrentLimit(failsafeCurrentLimit) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: failsafeCurrentLimit
        });
        await bp.send(this._ch, 192);
      }
      /**
       * The minimum value that `failsafeTime` can be set to when calling `enableFailsafe()`.
       * @returns The failsafe time
       * @throws `PhidgetError`
       */
      getMinFailsafeTime() {
        this._assertOpen();
        if (this.data.minFailsafeTime === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minFailsafeTime;
      }
      /**
       * The maximum value that `failsafeTime` can be set to when calling `enableFailsafe()`.
       * @returns The failsafe time
       * @throws `PhidgetError`
       */
      getMaxFailsafeTime() {
        this._assertOpen();
        if (this.data.maxFailsafeTime === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxFailsafeTime;
      }
      /**
       * The controller will attempt to measure the inductance of your motor when opened. This value is used to improve control of the motor.
       *
       * *   Set this value during the `Phidget.Attach` event to skip motor characterization (including the audible beeps). You can use a previously saved `inductance` value, or information from your motor's datasheet.
       *
       *
       * For more information about `inductance`, visit our [MotorVelocityController API Guide](https://www.phidgets.com/docs/MotorVelocityController_API_Guide#Motor_Inductance)
       * @returns The inductance of your motor
       * @throws `PhidgetError`
       */
      getInductance() {
        this._assertOpen();
        if (this.data.inductance === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.inductance;
      }
      /**
       * The controller will attempt to measure the inductance of your motor when opened. This value is used to improve control of the motor.
       *
       * *   Set this value during the `Phidget.Attach` event to skip motor characterization (including the audible beeps). You can use a previously saved `inductance` value, or information from your motor's datasheet.
       *
       *
       * For more information about `inductance`, visit our [MotorVelocityController API Guide](https://www.phidgets.com/docs/MotorVelocityController_API_Guide#Motor_Inductance)
       * @throws `PhidgetError`
       * @param inductance - The inductance of your motor
       */
      async setInductance(inductance) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: inductance
        });
        await bp.send(this._ch, 184);
      }
      /**
       * The minimum value that `inductance` can be set to. See `inductance` for details.
       * @returns The motor inductance value
       * @throws `PhidgetError`
       */
      getMinInductance() {
        this._assertOpen();
        if (this.data.minInductance === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minInductance;
      }
      /**
       * The maximum value that `inductance` can be set to. See `inductance` for details.
       * @returns The motor inductance value
       * @throws `PhidgetError`
       */
      getMaxInductance() {
        this._assertOpen();
        if (this.data.maxInductance === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxInductance;
      }
      /**
       * Change the units of your parameters so that your application is more intuitive.
       *
       * *   Units for `acceleration`, `deadBand`, `expectedVelocity`, `targetVelocity`, and `velocity` can be set by the user through the `rescaleFactor`. The `rescaleFactor` allows you to use more intuitive units such as rotations, or degrees.
       *
       *
       * For more information about `rescaleFactor`, visit our [MotorVelocityController API Guide](https://www.phidgets.com/docs/MotorVelocityController_API_Guide#Rescale_Factor)
       * @returns The rescale factor value
       * @throws `PhidgetError`
       */
      getRescaleFactor() {
        this._assertOpen();
        if (this.data.rescaleFactor === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.rescaleFactor;
      }
      /**
       * Resets the failsafe timer, if one has been set. See `enableFailsafe()` for details.
       *
       * This function will fail if no failsafe timer has been set for the channel.
       * @throws `PhidgetError`
       */
      async resetFailsafe() {
        this._assertOpen();
        const bp = new BridgePacket();
        await bp.send(this._ch, 147);
      }
      /**
       * The `surgeCurrentLimit` allows for increased performance from your motor. The controller will limit the current through your motor to the `surgeCurrentLimit` briefly, then scale current down to the `currentLimit`.
       *
       * *   View `activeCurrentLimit` for information about what current limit the controller is actively following.
       *
       *
       * For more information about `surgeCurrentLimit`, visit our [MotorVelocityController API Guide](https://www.phidgets.com/docs/MotorVelocityController_API_Guide#Surge_Current_Limit)
       * @returns The surge current limit value
       * @throws `PhidgetError`
       */
      getSurgeCurrentLimit() {
        this._assertOpen();
        if (this.data.surgeCurrentLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.surgeCurrentLimit;
      }
      /**
       * The `surgeCurrentLimit` allows for increased performance from your motor. The controller will limit the current through your motor to the `surgeCurrentLimit` briefly, then scale current down to the `currentLimit`.
       *
       * *   View `activeCurrentLimit` for information about what current limit the controller is actively following.
       *
       *
       * For more information about `surgeCurrentLimit`, visit our [MotorVelocityController API Guide](https://www.phidgets.com/docs/MotorVelocityController_API_Guide#Surge_Current_Limit)
       * @throws `PhidgetError`
       * @param surgeCurrentLimit - The surge current limit value
       */
      async setSurgeCurrentLimit(surgeCurrentLimit) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: surgeCurrentLimit
        });
        await bp.send(this._ch, 194);
      }
      /**
       * The minimum value that `surgeCurrentLimit` can be set to.
       * @returns The surge current value
       * @throws `PhidgetError`
       */
      getMinSurgeCurrentLimit() {
        this._assertOpen();
        if (this.data.minSurgeCurrentLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minSurgeCurrentLimit;
      }
      /**
       * The maximum value that `surgeCurrentLimit` can be set to.
       * @returns The surge current value
       * @throws `PhidgetError`
       */
      getMaxSurgeCurrentLimit() {
        this._assertOpen();
        if (this.data.maxSurgeCurrentLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxSurgeCurrentLimit;
      }
    }

    /** @internal */
    class MotorVelocityController extends MotorVelocityControllerBase {
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 100:
            this.data.velocity = bp.getNumber(0);
            if (this._isAttachedDone && this.onVelocityChange) {
              try {
                this.onVelocityChange(this.data.velocity * this.data.rescaleFactor);
              } catch (err) {
                logEventException(err);
              }
            }
            break;
          case 185:
            this.data.inductance = bp.getNumber(0);
            this._FIREPropertyChange("Inductance");
            break;
          case 10:
            if (bp.entryCount > 1) this.data.dataInterval = bp.getNumber(1);else this.data.dataInterval = bp.getNumber(0);
            this._FIREPropertyChange("DataInterval");
            this._FIREPropertyChange("DataRate");
            break;
          case 196:
            this.data.currentLimit = bp.getNumber(0);
            this._FIREPropertyChange("CurrentLimit");
            break;
          case 195:
            this.data.surgeCurrentLimit = bp.getNumber(0);
            this._FIREPropertyChange("SurgeCurrentLimit");
            break;
          case 197:
            {
              const activeCurrentLimit = bp.getNumber(0);
              if (this.data.activeCurrentLimit != activeCurrentLimit) {
                this.data.activeCurrentLimit = activeCurrentLimit;
                this._FIREPropertyChange("ActiveCurrentLimit");
              }
              break;
            }
          case 190:
            this.data.expectedVelocity = bp.getNumber(0);
            if (this._isAttachedDone && this.onExpectedVelocityChange) {
              try {
                this.onExpectedVelocityChange(this.data.expectedVelocity * this.data.rescaleFactor);
              } catch (err) {
                logEventException(err);
              }
            }
            break;
          default:
            super._bridgeInput(bp);
            break;
        }
      }
      /** @internal */
      async _setDefaults() {
        try {
          await super._setDefaults();
        } catch (err) {
          if (err instanceof PhidgetError) {
            switch (err.errorCode) {
              case exports.ErrorCode.FAILSAFE:
                err.message = "External stop procedure initiated.";
                break;
              case exports.ErrorCode.BAD_POWER:
                err.message = "Your power supply voltage is too high for the motor controller to begin operation.";
                break;
              case exports.ErrorCode.POWER_CYCLE:
                err.message = "An overvoltage fault has triggered. Power your device off and on to resume operation. We recommend a PowerGuard Phidget to prevent this in future.";
                break;
              case exports.ErrorCode.HALLSENSOR:
                err.message = "The hall sensor of your BLDC motor is not reporting a valid input. The cable is likely damaged or unplugged.";
                break;
              case exports.ErrorCode.BADCURRENT:
                err.message = "The current sensor is seeing an unacceptable offset in its readings. Move the controller away from magnetic fields and try again.";
                break;
            }
          }
          throw err;
        }
      }
      /** @internal */
      _errorHandler(code) {
        switch (code) {
          case exports.ErrorEventCode.MOTOR_STALL_CONDITION:
            this.data.engaged = 0;
            break;
        }
      }
      getAcceleration() {
        this._assertOpen();
        if (this.data.acceleration === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.acceleration * Math.abs(this.data.rescaleFactor);
      }
      async setAcceleration(acceleration) {
        this._assertOpen();
        const calcAccel = acceleration / Math.abs(this.data.rescaleFactor);
        if (calcAccel < this.data.minAcceleration || calcAccel > this.data.maxAcceleration) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Value must be in range: " + this.minAcceleration + " - " + this.maxAcceleration + ".");
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: calcAccel
        });
        await bp.send(this._ch, 40);
      }
      getMinAcceleration() {
        this._assertOpen();
        if (this.data.minAcceleration === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minAcceleration * Math.abs(this.data.rescaleFactor);
      }
      getMaxAcceleration() {
        this._assertOpen();
        if (this.data.maxAcceleration === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxAcceleration * Math.abs(this.data.rescaleFactor);
      }
      getVelocity() {
        this._assertOpen();
        if (this.data.velocity === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.velocity * this.data.rescaleFactor;
      }
      getMinTargetVelocity() {
        this._assertOpen();
        if (this.data.minTargetVelocity === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minTargetVelocity * Math.abs(this.data.rescaleFactor);
      }
      getMaxTargetVelocity() {
        this._assertOpen();
        if (this.data.maxTargetVelocity === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxTargetVelocity * Math.abs(this.data.rescaleFactor);
      }
      setRescaleFactor(rescaleFactor) {
        this._assertOpen();
        if (rescaleFactor === 0) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT);
        this.data.rescaleFactor = rescaleFactor;
      }
      getTargetVelocity() {
        this._assertOpen();
        if (this.data.targetVelocity === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.targetVelocity * this.data.rescaleFactor;
      }
      async setTargetVelocity(targetVelocity) {
        this._assertOpen();
        const calcVelocity = targetVelocity / this.data.rescaleFactor;
        if (calcVelocity < this.data.minTargetVelocity || calcVelocity > this.data.maxTargetVelocity) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Value must be in range: " + this.minTargetVelocity + " - " + this.maxTargetVelocity + ".");
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: calcVelocity
        });
        await bp.send(this._ch, 55);
      }
      getStallVelocity() {
        this._assertOpen();
        throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
      }
      async setStallVelocity(stallVelocity) {
        this._assertOpen();
        throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
      }
      getMinStallVelocity() {
        this._assertOpen();
        throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
      }
      getMaxStallVelocity() {
        this._assertOpen();
        throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
      }
      getKd() {
        this._assertOpen();
        if (this.data.kd === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.kd / Math.abs(this.data.rescaleFactor);
      }
      async setKd(kd) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: kd * Math.abs(this.data.rescaleFactor)
        });
        await bp.send(this._ch, 136);
      }
      getKi() {
        this._assertOpen();
        if (this.data.ki === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.ki / Math.abs(this.data.rescaleFactor);
      }
      async setKi(ki) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: ki * Math.abs(this.data.rescaleFactor)
        });
        await bp.send(this._ch, 142);
      }
      getKp() {
        this._assertOpen();
        if (this.data.kp === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.kp / Math.abs(this.data.rescaleFactor);
      }
      async setKp(kp) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: kp * Math.abs(this.data.rescaleFactor)
        });
        await bp.send(this._ch, 135);
      }
      async setDeadBand(deadband) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: deadband / Math.abs(this.data.rescaleFactor)
        });
        await bp.send(this._ch, 120);
      }
      getDeadBand() {
        this._assertOpen();
        if (this.data.deadBand === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.deadBand * Math.abs(this.data.rescaleFactor);
      }
      getExpectedVelocity() {
        this._assertOpen();
        if (this.data.expectedVelocity === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.expectedVelocity * this.data.rescaleFactor;
      }
      getPositionType() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 305:
          case 312:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.positionType === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.positionType;
      }
      async setPositionType(positionType) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: positionType
        });
        await bp.send(this._ch, 187);
        switch (this._ch?.chDef.uid) {
          case 305:
          case 312:
            switch (positionType) {
              case exports.PositionType.ENCODER:
                this.data.maxTargetVelocity = 500000;
                this.data.minTargetVelocity = -5e5;
                break;
              case exports.PositionType.HALL_SENSOR:
                this.data.maxTargetVelocity = 2000;
                this.data.minTargetVelocity = -2e3;
                break;
            }
            break;
        }
      }
    }

    /**
     * The PH Sensor class gathers data from a pH sensor type Phidget board.
     *
     * If you're using a simple 0-5V sensor that does not have its own firmware, use the VoltageInput or VoltageRatioInput class instead, as specified for your device.
     * @public
     */
    class PHSensorBase extends PhidgetChannel {
      /** @internal */
      data;
      onPHChange = null;
      /** @internal */
      _gotPHChangeErrorEvent;
      constructor(ch) {
        super(ch);
        this._class = exports.ChannelClass.PH_SENSOR;
        this.name = "PHSensor";
        this.data = this._initData();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 134:
            this.data.correctionTemperature = bp.entries[0].v;
            this._FIREPropertyChange('CorrectionTemperature', bp);
            break;
          case 54:
            if (bp.entryCount > 1) this.data.dataInterval = bp.entries[1].v;else this.data.dataInterval = bp.entries[0].v;
            this._FIREPropertyChange('DataInterval', bp);
            this._FIREPropertyChange('DataRate', bp);
            break;
          case 46:
            this.data.PHChangeTrigger = bp.entries[0].v;
            this._FIREPropertyChange('PHChangeTrigger', bp);
            break;
          case 133:
            {
              this.data.PH = bp.entries[0].v;
              if (this._isAttachedDone && this.onPHChange) {
                try {
                  this.onPHChange(this.data.PH);
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          default:
            throw new PhidgetError(exports.ErrorCode.INVALID_PACKET, "Unsupported bridge packet: 0x" + bp.vpkt.toString(16));
        }
      }
      /** @internal */
      _initData() {
        return {
          dataInterval: 1e+300,
          maxDataInterval: 4294967295,
          minDataRate: 1e+300,
          maxDataRate: 1e+300,
          maxPH: 1e+300,
          maxPHChangeTrigger: 1e+300,
          minDataInterval: 4294967295,
          minPH: 1e+300,
          minPHChangeTrigger: 1e+300,
          PH: 1e+300,
          PHChangeTrigger: 1e+300,
          correctionTemperature: 1e+300,
          minCorrectionTemperature: 1e+300,
          maxCorrectionTemperature: 1e+300
        };
      }
      /** @internal */
      _initAfterOpen() {}
      /** @internal */
      async _setDefaults() {}
      /** @internal */
      _hasInitialState() {
        return true;
      }
      /** @internal */
      _fireInitialEvents() {}
      /**
       * Set this property to the measured temperature of the solution to correct the slope of the pH conversion for temperature.
       * @throws `PhidgetError`
       */
      get correctionTemperature() {
        return this.getCorrectionTemperature();
      }
      /**
       * The minimum value that `correctionTemperature` can be set to.
       * @throws `PhidgetError`
       */
      get minCorrectionTemperature() {
        return this.getMinCorrectionTemperature();
      }
      /**
       * The maximum value that `correctionTemperature` can be set to.
       * @throws `PhidgetError`
       */
      get maxCorrectionTemperature() {
        return this.getMaxCorrectionTemperature();
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `PHChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between `PHChange` events can also be affected by the `PHChangeTrigger`.
       * @throws `PhidgetError`
       */
      get dataInterval() {
        return this.getDataInterval();
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get minDataInterval() {
        return this.getMinDataInterval();
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataInterval() {
        return this.getMaxDataInterval();
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       */
      get dataRate() {
        return this.getDataRate();
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get minDataRate() {
        return this.getMinDataRate();
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataRate() {
        return this.getMaxDataRate();
      }
      /**
       * The most recent pH value that the channel has reported.
       *
       * *   This value will always be between `minPH` and `maxPH`.
       * @throws `PhidgetError`
       */
      get PH() {
        return this.getPH();
      }
      /**
       * The minimum value the `PHChange` event will report.
       * @throws `PhidgetError`
       */
      get minPH() {
        return this.getMinPH();
      }
      /**
       * The maximum value the `PHChange` event will report.
       * @throws `PhidgetError`
       */
      get maxPH() {
        return this.getMaxPH();
      }
      /**
       * The channel will not issue a `PHChange` event until the pH value has changed by the amount specified by the `PHChangeTrigger`.
       *
       * *   Setting the `PHChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @throws `PhidgetError`
       */
      get PHChangeTrigger() {
        return this.getPHChangeTrigger();
      }
      /**
       * The minimum value that `PHChangeTrigger` can be set to.
       * @throws `PhidgetError`
       */
      get minPHChangeTrigger() {
        return this.getMinPHChangeTrigger();
      }
      /**
       * The maximum value that `PHChangeTrigger` can be set to.
       * @throws `PhidgetError`
       */
      get maxPHChangeTrigger() {
        return this.getMaxPHChangeTrigger();
      }
      /**
       * Set this property to the measured temperature of the solution to correct the slope of the pH conversion for temperature.
       * @returns The temperature of the solution to correct the pH measurement.
       * @throws `PhidgetError`
       */
      getCorrectionTemperature() {
        this._assertOpen();
        if (this.data.correctionTemperature === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.correctionTemperature;
      }
      /**
       * Set this property to the measured temperature of the solution to correct the slope of the pH conversion for temperature.
       * @throws `PhidgetError`
       * @param correctionTemperature - The temperature of the solution to correct the pH measurement.
       */
      async setCorrectionTemperature(correctionTemperature) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: correctionTemperature
        });
        await bp.send(this._ch, 134);
      }
      /**
       * The minimum value that `correctionTemperature` can be set to.
       * @returns The minimum temperature that can be corrected for.
       * @throws `PhidgetError`
       */
      getMinCorrectionTemperature() {
        this._assertOpen();
        if (this.data.minCorrectionTemperature === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minCorrectionTemperature;
      }
      /**
       * The maximum value that `correctionTemperature` can be set to.
       * @returns The maximum temperature that can be corrected for.
       * @throws `PhidgetError`
       */
      getMaxCorrectionTemperature() {
        this._assertOpen();
        if (this.data.maxCorrectionTemperature === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxCorrectionTemperature;
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `PHChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between `PHChange` events can also be affected by the `PHChangeTrigger`.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getDataInterval() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.dataInterval;
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `PHChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between `PHChange` events can also be affected by the `PHChangeTrigger`.
       * @throws `PhidgetError`
       * @param dataInterval - The data interval value
       */
      async setDataInterval(dataInterval) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: dataInterval
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMinDataInterval() {
        this._assertOpen();
        if (this.data.minDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataInterval;
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMaxDataInterval() {
        this._assertOpen();
        if (this.data.maxDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @returns The data rate for the channel
       * @throws `PhidgetError`
       */
      getDataRate() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return 1000.0 / this.data.dataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       * @param dataRate - The data rate for the channel
       */
      async setDataRate(dataRate) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: Math.round(1000.0 / dataRate)
        });
        bp.set({
          name: "1",
          type: "g",
          value: 1000.0 / dataRate
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMinDataRate() {
        this._assertOpen();
        if (this.data.minDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataRate;
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMaxDataRate() {
        this._assertOpen();
        if (this.data.maxDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataRate;
      }
      /**
       * The most recent pH value that the channel has reported.
       *
       * *   This value will always be between `minPH` and `maxPH`.
       * @returns The pH value
       * @throws `PhidgetError`
       */
      getPH() {
        this._assertOpen();
        if (this.data.PH === 1e+300 || Number.isNaN(this.data.PH)) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        if (this.data.PH > this.data.maxPH) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE_HIGH);
        if (this.data.PH < this.data.minPH) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE_LOW);
        return this.data.PH;
      }
      /**
       * The minimum value the `PHChange` event will report.
       * @returns The pH value
       * @throws `PhidgetError`
       */
      getMinPH() {
        this._assertOpen();
        if (this.data.minPH === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minPH;
      }
      /**
       * The maximum value the `PHChange` event will report.
       * @returns The pH value
       * @throws `PhidgetError`
       */
      getMaxPH() {
        this._assertOpen();
        if (this.data.maxPH === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxPH;
      }
      /**
       * The channel will not issue a `PHChange` event until the pH value has changed by the amount specified by the `PHChangeTrigger`.
       *
       * *   Setting the `PHChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getPHChangeTrigger() {
        this._assertOpen();
        if (this.data.PHChangeTrigger === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.PHChangeTrigger;
      }
      /**
       * The channel will not issue a `PHChange` event until the pH value has changed by the amount specified by the `PHChangeTrigger`.
       *
       * *   Setting the `PHChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @throws `PhidgetError`
       * @param PHChangeTrigger - The change trigger value
       */
      async setPHChangeTrigger(PHChangeTrigger) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: PHChangeTrigger
        });
        await bp.send(this._ch, 46);
      }
      /**
       * The minimum value that `PHChangeTrigger` can be set to.
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getMinPHChangeTrigger() {
        this._assertOpen();
        if (this.data.minPHChangeTrigger === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minPHChangeTrigger;
      }
      /**
       * The maximum value that `PHChangeTrigger` can be set to.
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getMaxPHChangeTrigger() {
        this._assertOpen();
        if (this.data.maxPHChangeTrigger === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxPHChangeTrigger;
      }
    }

    /** @public */
    class PHSensor extends PHSensorBase {}

    /**
     * The Power Guard class controls the safety features and thresholds of a programmable power guard Phidget board.
     * @public
     */
    class PowerGuardBase extends PhidgetChannel {
      /** @internal */
      data;
      constructor(ch) {
        super(ch);
        this._class = exports.ChannelClass.POWER_GUARD;
        this.name = "PowerGuard";
        this.data = this._initData();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 146:
            break;
          case 58:
            this.data.fanMode = bp.entries[0].v;
            this._FIREPropertyChange('FanMode', bp);
            break;
          case 71:
            this.data.overVoltage = bp.entries[0].v;
            this._FIREPropertyChange('OverVoltage', bp);
            break;
          case 56:
            this.data.powerEnabled = bp.entries[0].v;
            this._FIREPropertyChange('PowerEnabled', bp);
            break;
          case 147:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.INVALID_PACKET, "Unsupported bridge packet: 0x" + bp.vpkt.toString(16));
        }
      }
      /** @internal */
      _initData() {
        return {
          powerEnabled: 2,
          overVoltage: 1e+300,
          maxOverVoltage: 1e+300,
          minOverVoltage: 1e+300,
          fanMode: 2147483647,
          maxFailsafeTime: 4294967295,
          minFailsafeTime: 4294967295
        };
      }
      /** @internal */
      _initAfterOpen() {}
      /** @internal */
      async _setDefaults() {}
      /** @internal */
      _hasInitialState() {
        return true;
      }
      /** @internal */
      _fireInitialEvents() {}
      /**
       * The minimum value that `failsafeTime` can be set to when calling `enableFailsafe()`.
       * @throws `PhidgetError`
       */
      get minFailsafeTime() {
        return this.getMinFailsafeTime();
      }
      /**
       * The maximum value that `failsafeTime` can be set to when calling `enableFailsafe()`.
       * @throws `PhidgetError`
       */
      get maxFailsafeTime() {
        return this.getMaxFailsafeTime();
      }
      /**
       * The `fanMode` dictates the operating condition of the fan.
       *
       * *   Choose between on, off, or automatic (based on temperature).
       * *   If the `fanMode` is set to automatic, the fan will turn on when the temperature reaches 70°C and it will remain on until the temperature falls below 55°C.
       * *   If the `fanMode` is off, the device will still turn on the fan if the temperature reaches 85°C and it will remain on until it falls below 70°C.
       * @throws `PhidgetError`
       */
      get fanMode() {
        return this.getFanMode();
      }
      /**
       * The device constantly monitors the output voltage, and if it exceeds the `overVoltage` value, it will disconnect the input from the output.
       *
       * *   This functionality is critical for protecting power supplies from regenerated voltage coming from motors. Many power supplies assume that a higher than output expected voltage is related to an internal failure to the power supply, and will permanently disable themselves to protect the system. A typical safe value is to set OverVoltage to 1-2 volts higher than the output voltage of the supply. For instance, a 12V supply would be protected by setting OverVoltage to 13V.
       * *   The device will connect the input to the output again when the voltage drops to (`overVoltage` - 1V)
       * @throws `PhidgetError`
       */
      get overVoltage() {
        return this.getOverVoltage();
      }
      /**
       * The minimum value that `overVoltage` can be set to.
       * @throws `PhidgetError`
       */
      get minOverVoltage() {
        return this.getMinOverVoltage();
      }
      /**
       * The maximum value that `overVoltage` can be set to.
       * @throws `PhidgetError`
       */
      get maxOverVoltage() {
        return this.getMaxOverVoltage();
      }
      /**
       * When `powerEnabled` is true, the device will connect the input to the output and begin monitoring.
       *
       * *   The output voltage is constantly monitored and will be automatically disconnected from the input when the output exceeds the `overVoltage` value.
       * *   `powerEnabled` allows the device to operate as a Solid State Relay, powering on or off all devices connected to the output.
       * @throws `PhidgetError`
       */
      get powerEnabled() {
        return this.getPowerEnabled();
      }
      /**
       * Enables the **failsafe** feature for the channel, with the specified **failsafe time**.
       *
       * Enabling the failsafe feature starts a recurring **failsafe timer** for the channel. Once the failsafe is enabled, the timer must be reset within the specified time or the channel will enter a **failsafe state**. For Power Guard channels, this will turn off the output. The failsafe timer can be reset by using any of the following API calls:
       *
       * *   `setFanMode()`
       * *   `setOverVoltage()`
       * *   `setPowerEnabled()`
       * *   `resetFailsafe()`
       *
       * For more information about failsafe, visit our [Failsafe Guide](https://www.phidgets.com/docs/Failsafe_Guide).
       * @throws `PhidgetError`
       * @param failsafeTime - Failsafe timeout in milliseconds
       */
      async enableFailsafe(failsafeTime) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: failsafeTime
        });
        await bp.send(this._ch, 146);
      }
      /**
       * The minimum value that `failsafeTime` can be set to when calling `enableFailsafe()`.
       * @returns The failsafe time
       * @throws `PhidgetError`
       */
      getMinFailsafeTime() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 417:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.minFailsafeTime === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minFailsafeTime;
      }
      /**
       * The maximum value that `failsafeTime` can be set to when calling `enableFailsafe()`.
       * @returns The failsafe time
       * @throws `PhidgetError`
       */
      getMaxFailsafeTime() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 417:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.maxFailsafeTime === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxFailsafeTime;
      }
      /**
       * The `fanMode` dictates the operating condition of the fan.
       *
       * *   Choose between on, off, or automatic (based on temperature).
       * *   If the `fanMode` is set to automatic, the fan will turn on when the temperature reaches 70°C and it will remain on until the temperature falls below 55°C.
       * *   If the `fanMode` is off, the device will still turn on the fan if the temperature reaches 85°C and it will remain on until it falls below 70°C.
       * @returns The fan mode value
       * @throws `PhidgetError`
       */
      getFanMode() {
        this._assertOpen();
        if (this.data.fanMode === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.fanMode;
      }
      /**
       * The `fanMode` dictates the operating condition of the fan.
       *
       * *   Choose between on, off, or automatic (based on temperature).
       * *   If the `fanMode` is set to automatic, the fan will turn on when the temperature reaches 70°C and it will remain on until the temperature falls below 55°C.
       * *   If the `fanMode` is off, the device will still turn on the fan if the temperature reaches 85°C and it will remain on until it falls below 70°C.
       * @throws `PhidgetError`
       * @param fanMode - The fan mode value
       */
      async setFanMode(fanMode) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: fanMode
        });
        await bp.send(this._ch, 58);
      }
      /**
       * The device constantly monitors the output voltage, and if it exceeds the `overVoltage` value, it will disconnect the input from the output.
       *
       * *   This functionality is critical for protecting power supplies from regenerated voltage coming from motors. Many power supplies assume that a higher than output expected voltage is related to an internal failure to the power supply, and will permanently disable themselves to protect the system. A typical safe value is to set OverVoltage to 1-2 volts higher than the output voltage of the supply. For instance, a 12V supply would be protected by setting OverVoltage to 13V.
       * *   The device will connect the input to the output again when the voltage drops to (`overVoltage` - 1V)
       * @returns The voltage value
       * @throws `PhidgetError`
       */
      getOverVoltage() {
        this._assertOpen();
        if (this.data.overVoltage === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.overVoltage;
      }
      /**
       * The device constantly monitors the output voltage, and if it exceeds the `overVoltage` value, it will disconnect the input from the output.
       *
       * *   This functionality is critical for protecting power supplies from regenerated voltage coming from motors. Many power supplies assume that a higher than output expected voltage is related to an internal failure to the power supply, and will permanently disable themselves to protect the system. A typical safe value is to set OverVoltage to 1-2 volts higher than the output voltage of the supply. For instance, a 12V supply would be protected by setting OverVoltage to 13V.
       * *   The device will connect the input to the output again when the voltage drops to (`overVoltage` - 1V)
       * @throws `PhidgetError`
       * @param overVoltage - The voltage value
       */
      async setOverVoltage(overVoltage) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: overVoltage
        });
        await bp.send(this._ch, 71);
      }
      /**
       * The minimum value that `overVoltage` can be set to.
       * @returns The voltage value
       * @throws `PhidgetError`
       */
      getMinOverVoltage() {
        this._assertOpen();
        if (this.data.minOverVoltage === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minOverVoltage;
      }
      /**
       * The maximum value that `overVoltage` can be set to.
       * @returns The voltage value
       * @throws `PhidgetError`
       */
      getMaxOverVoltage() {
        this._assertOpen();
        if (this.data.maxOverVoltage === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxOverVoltage;
      }
      /**
       * When `powerEnabled` is true, the device will connect the input to the output and begin monitoring.
       *
       * *   The output voltage is constantly monitored and will be automatically disconnected from the input when the output exceeds the `overVoltage` value.
       * *   `powerEnabled` allows the device to operate as a Solid State Relay, powering on or off all devices connected to the output.
       * @returns The power enabled value.
       * @throws `PhidgetError`
       */
      getPowerEnabled() {
        this._assertOpen();
        if (this.data.powerEnabled === 2) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return !!this.data.powerEnabled;
      }
      /**
       * When `powerEnabled` is true, the device will connect the input to the output and begin monitoring.
       *
       * *   The output voltage is constantly monitored and will be automatically disconnected from the input when the output exceeds the `overVoltage` value.
       * *   `powerEnabled` allows the device to operate as a Solid State Relay, powering on or off all devices connected to the output.
       * @throws `PhidgetError`
       * @param powerEnabled - The power enabled value.
       */
      async setPowerEnabled(powerEnabled) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: powerEnabled ? 1 : 0
        });
        await bp.send(this._ch, 56);
      }
      /**
       * Resets the failsafe timer, if one has been set. See `enableFailsafe()` for details.
       *
       * This function will fail if no failsafe timer has been set for the channel.
       * @throws `PhidgetError`
       */
      async resetFailsafe() {
        this._assertOpen();
        const bp = new BridgePacket();
        await bp.send(this._ch, 147);
      }
    }

    /** @public */
    class PowerGuard extends PowerGuardBase {}

    /**
     * The Pressure Sensor class gathers data from the pressure sensor on a Phidget board.
     *
     * If you're using a simple 0-5V sensor that does not have its own firmware, use the VoltageInput or VoltageRatioInput class instead, as specified for your device.
     * @public
     */
    class PressureSensorBase extends PhidgetChannel {
      /** @internal */
      data;
      onPressureChange = null;
      /** @internal */
      _gotPressureChangeErrorEvent;
      constructor(ch) {
        super(ch);
        this._class = exports.ChannelClass.PRESSURE_SENSOR;
        this.name = "PressureSensor";
        this.data = this._initData();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 54:
            if (bp.entryCount > 1) this.data.dataInterval = bp.entries[1].v;else this.data.dataInterval = bp.entries[0].v;
            this._FIREPropertyChange('DataInterval', bp);
            this._FIREPropertyChange('DataRate', bp);
            break;
          case 46:
            this.data.pressureChangeTrigger = bp.entries[0].v;
            this._FIREPropertyChange('PressureChangeTrigger', bp);
            break;
          case 31:
            {
              this.data.pressure = bp.entries[0].v;
              if (this._isAttachedDone && this.onPressureChange) {
                try {
                  this.onPressureChange(this.data.pressure);
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          default:
            throw new PhidgetError(exports.ErrorCode.INVALID_PACKET, "Unsupported bridge packet: 0x" + bp.vpkt.toString(16));
        }
      }
      /** @internal */
      _initData() {
        return {
          dataInterval: 1e+300,
          maxDataInterval: 4294967295,
          minDataRate: 1e+300,
          maxDataRate: 1e+300,
          maxPressure: 1e+300,
          maxPressureChangeTrigger: 1e+300,
          minDataInterval: 4294967295,
          minPressure: 1e+300,
          minPressureChangeTrigger: 1e+300,
          pressure: 1e+300,
          pressureChangeTrigger: 1e+300
        };
      }
      /** @internal */
      _initAfterOpen() {}
      /** @internal */
      async _setDefaults() {}
      /** @internal */
      _hasInitialState() {
        return true;
      }
      /** @internal */
      _fireInitialEvents() {}
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `PressureChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between `PressureChange` events can also be affected by the `pressureChangeTrigger`.
       * @throws `PhidgetError`
       */
      get dataInterval() {
        return this.getDataInterval();
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get minDataInterval() {
        return this.getMinDataInterval();
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataInterval() {
        return this.getMaxDataInterval();
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       */
      get dataRate() {
        return this.getDataRate();
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get minDataRate() {
        return this.getMinDataRate();
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataRate() {
        return this.getMaxDataRate();
      }
      /**
       * The most recent pressure value that the channel has reported.
       *
       * *   This value will always be between `minPressure` and `maxPressure`.
       * @throws `PhidgetError`
       */
      get pressure() {
        return this.getPressure();
      }
      /**
       * The minimum value the `PressureChange` event will report.
       * @throws `PhidgetError`
       */
      get minPressure() {
        return this.getMinPressure();
      }
      /**
       * The maximum value the `PressureChange` event will report.
       * @throws `PhidgetError`
       */
      get maxPressure() {
        return this.getMaxPressure();
      }
      /**
       * The channel will not issue a `PressureChange` event until the pressure value has changed by the amount specified by the `pressureChangeTrigger`.
       *
       * *   Setting the `pressureChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @throws `PhidgetError`
       */
      get pressureChangeTrigger() {
        return this.getPressureChangeTrigger();
      }
      /**
       * The minimum value that `pressureChangeTrigger` can be set to.
       * @throws `PhidgetError`
       */
      get minPressureChangeTrigger() {
        return this.getMinPressureChangeTrigger();
      }
      /**
       * The maximum value that `pressureChangeTrigger` can be set to.
       * @throws `PhidgetError`
       */
      get maxPressureChangeTrigger() {
        return this.getMaxPressureChangeTrigger();
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `PressureChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between `PressureChange` events can also be affected by the `pressureChangeTrigger`.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getDataInterval() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.dataInterval;
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `PressureChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between `PressureChange` events can also be affected by the `pressureChangeTrigger`.
       * @throws `PhidgetError`
       * @param dataInterval - The data interval value
       */
      async setDataInterval(dataInterval) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: dataInterval
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMinDataInterval() {
        this._assertOpen();
        if (this.data.minDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataInterval;
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMaxDataInterval() {
        this._assertOpen();
        if (this.data.maxDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @returns The data rate for the channel
       * @throws `PhidgetError`
       */
      getDataRate() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return 1000.0 / this.data.dataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       * @param dataRate - The data rate for the channel
       */
      async setDataRate(dataRate) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: Math.round(1000.0 / dataRate)
        });
        bp.set({
          name: "1",
          type: "g",
          value: 1000.0 / dataRate
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMinDataRate() {
        this._assertOpen();
        if (this.data.minDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataRate;
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMaxDataRate() {
        this._assertOpen();
        if (this.data.maxDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataRate;
      }
      /**
       * The most recent pressure value that the channel has reported.
       *
       * *   This value will always be between `minPressure` and `maxPressure`.
       * @returns The pressure value
       * @throws `PhidgetError`
       */
      getPressure() {
        this._assertOpen();
        if (this.data.pressure === 1e+300 || Number.isNaN(this.data.pressure)) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        if (this.data.pressure > this.data.maxPressure) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE_HIGH);
        if (this.data.pressure < this.data.minPressure) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE_LOW);
        return this.data.pressure;
      }
      /**
       * The minimum value the `PressureChange` event will report.
       * @returns The pressure value
       * @throws `PhidgetError`
       */
      getMinPressure() {
        this._assertOpen();
        if (this.data.minPressure === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minPressure;
      }
      /**
       * The maximum value the `PressureChange` event will report.
       * @returns The pressure value
       * @throws `PhidgetError`
       */
      getMaxPressure() {
        this._assertOpen();
        if (this.data.maxPressure === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxPressure;
      }
      /**
       * The channel will not issue a `PressureChange` event until the pressure value has changed by the amount specified by the `pressureChangeTrigger`.
       *
       * *   Setting the `pressureChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getPressureChangeTrigger() {
        this._assertOpen();
        if (this.data.pressureChangeTrigger === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.pressureChangeTrigger;
      }
      /**
       * The channel will not issue a `PressureChange` event until the pressure value has changed by the amount specified by the `pressureChangeTrigger`.
       *
       * *   Setting the `pressureChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @throws `PhidgetError`
       * @param pressureChangeTrigger - The change trigger value
       */
      async setPressureChangeTrigger(pressureChangeTrigger) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: pressureChangeTrigger
        });
        await bp.send(this._ch, 46);
      }
      /**
       * The minimum value that `pressureChangeTrigger` can be set to.
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getMinPressureChangeTrigger() {
        this._assertOpen();
        if (this.data.minPressureChangeTrigger === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minPressureChangeTrigger;
      }
      /**
       * The maximum value that `pressureChangeTrigger` can be set to.
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getMaxPressureChangeTrigger() {
        this._assertOpen();
        if (this.data.maxPressureChangeTrigger === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxPressureChangeTrigger;
      }
    }

    /** @public */
    class PressureSensor extends PressureSensorBase {
      /** @internal */
      _errorHandler(code) {
        switch (code) {
          case exports.ErrorEventCode.SATURATION:
            this.data.pressure = 1e+300;
            this._gotPressureChangeErrorEvent = true;
            break;
        }
      }
    }

    /**
     * The RC Servo class controls the signal being sent to the servo motors from the Phidget controller in order to control their position. This class provides control of the position, velocity, acceleration, and supply voltage of the attached servo.
     * @public
     */
    class RCServoBase extends PhidgetChannel {
      /** @internal */
      data;
      onPositionChange = null;
      /** @internal */
      _gotPositionChangeErrorEvent;
      onVelocityChange = null;
      /** @internal */
      _gotVelocityChangeErrorEvent;
      onTargetPositionReached = null;
      /** @internal */
      _gotTargetPositionReachedErrorEvent;
      constructor(ch) {
        super(ch);
        this._class = exports.ChannelClass.RC_SERVO;
        this.name = "RCServo";
        this.data = this._initData();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 40:
            this.data.acceleration = bp.entries[0].v;
            this._FIREPropertyChange('Acceleration', bp);
            break;
          case 54:
            if (bp.entryCount > 1) this.data.dataInterval = bp.entries[1].v;else this.data.dataInterval = bp.entries[0].v;
            this._FIREPropertyChange('DataInterval', bp);
            this._FIREPropertyChange('DataRate', bp);
            break;
          case 57:
            this.data.engaged = bp.entries[0].v;
            this._FIREPropertyChange('Engaged', bp);
            break;
          case 146:
            break;
          case 70:
            this.data.minPulseWidth = bp.entries[0].v;
            this._FIREPropertyChange('MinPulseWidth', bp);
            break;
          case 69:
            this.data.maxPulseWidth = bp.entries[0].v;
            this._FIREPropertyChange('MaxPulseWidth', bp);
            break;
          case 147:
            break;
          case 81:
            this.data.speedRampingState = bp.entries[0].v;
            this._FIREPropertyChange('SpeedRampingState', bp);
            break;
          case 83:
            this.data.targetPosition = bp.entries[0].v;
            this._FIREPropertyChange('TargetPosition', bp);
            break;
          case 55:
            this.data.torque = bp.entries[0].v;
            this._FIREPropertyChange('Torque', bp);
            break;
          case 85:
            this.data.velocityLimit = bp.entries[0].v;
            this._FIREPropertyChange('VelocityLimit', bp);
            break;
          case 86:
            this.data.voltage = bp.entries[0].v;
            this._FIREPropertyChange('Voltage', bp);
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.INVALID_PACKET, "Unsupported bridge packet: 0x" + bp.vpkt.toString(16));
        }
      }
      /** @internal */
      _initData() {
        return {
          maxPulseWidthLimit: 1e+300,
          maxPulseWidth: 1e+300,
          maxPosition: 1e+300,
          maxVelocityLimit: 1e+300,
          maxAcceleration: 1e+300,
          maxTorque: 1e+300,
          minTorque: 1e+300,
          minPulseWidthLimit: 1e+300,
          minPulseWidth: 1e+300,
          minPosition: 1e+300,
          minVelocityLimit: 1e+300,
          minAcceleration: 1e+300,
          position: 1e+300,
          targetPosition: 1e+300,
          velocityLimit: 1e+300,
          velocity: 1e+300,
          acceleration: 1e+300,
          torque: 1e+300,
          isMoving: 2,
          engaged: 2,
          speedRampingState: 2,
          voltage: 2147483647,
          dataInterval: 1e+300,
          maxDataInterval: 4294967295,
          minDataInterval: 4294967295,
          minDataRate: 1e+300,
          maxDataRate: 1e+300,
          maxFailsafeTime: 4294967295,
          minFailsafeTime: 4294967295
        };
      }
      /** @internal */
      _initAfterOpen() {}
      /** @internal */
      async _setDefaults() {}
      /** @internal */
      _hasInitialState() {
        return true;
      }
      /** @internal */
      _fireInitialEvents() {}
      /**
       * When changing velocity, the RC servo motor will accelerate/decelerate at this rate.
       *
       * *   The acceleration is bounded by `maxAcceleration` and `minAcceleration`.
       *
       * *   Using the **default settings** this acceleration will correspond acceleration of servo arm in **degrees/s2**, for many standard RC servos.
       *
       * *   `speedRampingState` controls whether or not the acceleration value is actually applied when trying to reach a target position.
       * *   There is a practical limit on how fast your RC servo motor can accelerate. This is based on the load and physical design of the motor.
       * *   The units for `targetPosition`, `velocityLimit`, and `acceleration` are configured by scaling the internal timing (set with `minPulseWidth` and `maxPulseWidth`) to a user specified range with `minPosition` and `maxPosition`.
       *
       *
       *
       * See `targetPosition` for a deeper explanation of how the settings of your RC Servo controller interact to move your servo.
       * @throws `PhidgetError`
       */
      get acceleration() {
        return this.getAcceleration();
      }
      /**
       * The minimum value that `acceleration` can be set to.
       *
       * *   This value depends on `minPosition`/`maxPosition` and `minPulseWidth`/`maxPulseWidth`
       * .
       *
       *
       *
       * See `targetPosition` for a deeper explanation of how the settings of your RC Servo controller interact to move your servo.
       * @throws `PhidgetError`
       */
      get minAcceleration() {
        return this.getMinAcceleration();
      }
      /**
       * The maximum acceleration that `acceleration` can be set to.
       *
       * *   This value depends on `minPosition`/`maxPosition` and `minPulseWidth`/`maxPulseWidth`.
       *
       *
       *
       * See `targetPosition` for a deeper explanation of how the settings of your RC Servo controller interact to move your servo.
       * @throws `PhidgetError`
       */
      get maxAcceleration() {
        return this.getMaxAcceleration();
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `PositionChange` / `VelocityChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * @throws `PhidgetError`
       */
      get dataInterval() {
        return this.getDataInterval();
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get minDataInterval() {
        return this.getMinDataInterval();
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataInterval() {
        return this.getMaxDataInterval();
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       */
      get dataRate() {
        return this.getDataRate();
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get minDataRate() {
        return this.getMinDataRate();
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataRate() {
        return this.getMaxDataRate();
      }
      /**
       * When engaged, a RC servo motor has the ability to be positioned. When disengaged, no commands are sent to the RC servo motor.
       *
       * *   There is no position feedback to the controller, so the RC servo motor will immediately snap to the `targetPosition` after being engaged from a disengaged state.
       * *   This property is useful for relaxing a servo once it has reached a given position.
       * *   If you are concerned about tracking position accurately, you should not disengage the motor while `isMoving` is true.
       * @throws `PhidgetError`
       */
      get engaged() {
        return this.getEngaged();
      }
      /**
       * The minimum value that `failsafeTime` can be set to when calling `enableFailsafe()`.
       * @throws `PhidgetError`
       */
      get minFailsafeTime() {
        return this.getMinFailsafeTime();
      }
      /**
       * The maximum value that `failsafeTime` can be set to when calling `enableFailsafe()`.
       * @throws `PhidgetError`
       */
      get maxFailsafeTime() {
        return this.getMaxFailsafeTime();
      }
      /**
       * `isMoving` returns true if the RC servo motor is currently in motion.
       *
       * *   The controller cannot know if the RC servo motor is physically moving. When `isMoving` is false, it simply means there are no commands in the pipeline to the RC servo motor.
       * @throws `PhidgetError`
       */
      get isMoving() {
        return this.getIsMoving();
      }
      /**
       * The most recent position of the RC servo motor that the controller has reported.
       *
       * *   This value will always be between `minPosition` and `maxPosition`.
       *
       * *   Using the **default settings** this position will correspond to the rotation of the servo arm in **degrees**, for many standard RC servos.
       *
       *
       *
       * See `targetPosition` for a deeper explanation of how the settings of your RC Servo controller interact to move your servo.
       * @throws `PhidgetError`
       */
      get position() {
        return this.getPosition();
      }
      /**
       * The minimum position that `targetPosition` can be set to.
       *
       * *   The units for `targetPosition`, `velocityLimit`, and `acceleration` are configured by scaling the internal timing (set with `minPulseWidth` and `maxPulseWidth`) to a user specified range with `minPosition` and `maxPosition`.
       *
       *
       *
       * See `targetPosition` for a deeper explanation of how the settings of your RC Servo controller interact to move your servo.
       * @throws `PhidgetError`
       */
      get minPosition() {
        return this.getMinPosition();
      }
      set minPosition(minPosition) {
        this.setMinPosition(minPosition);
      }
      /**
       * The maximum position `targetPosition` can be set to.
       *
       * *   The units for `targetPosition`, `velocityLimit`, and `acceleration` are configured by scaling the internal timing (set with `minPulseWidth` and `maxPulseWidth`) to a user specified range with `minPosition` and `maxPosition`.
       *
       *
       *
       * See `targetPosition` for a deeper explanation of how the settings of your RC Servo controller interact to move your servo.
       * @throws `PhidgetError`
       */
      get maxPosition() {
        return this.getMaxPosition();
      }
      set maxPosition(maxPosition) {
        this.setMaxPosition(maxPosition);
      }
      /**
       * The `minPulseWidth` represents the minimum pulse width that your RC servo motor specifies.
       *
       * *   This value can be found in the data sheet of most RC servo motors.
       * *   The units for `targetPosition`, `velocityLimit`, and `acceleration` are configured by scaling the internal timing (set with `minPulseWidth` and `maxPulseWidth`) to a user specified range with `minPosition` and `maxPosition`.
       *
       *
       *
       * See `targetPosition` for a deeper explanation of how the settings of your RC Servo controller interact to move your servo.
       * @throws `PhidgetError`
       */
      get minPulseWidth() {
        return this.getMinPulseWidth();
      }
      /**
       * The `maxPulseWidth` represents the maximum pulse width that your RC servo motor specifies.
       *
       * *   This value can be found in the data sheet of most RC servo motors.
       * *   The units for `targetPosition`, `velocityLimit`, and `acceleration` are configured by scaling the internal timing (set with `minPulseWidth` and `maxPulseWidth`) to a user specified range with `minPosition` and `maxPosition`.
       *
       *
       *
       * See `targetPosition` for a deeper explanation of how the settings of your RC Servo controller interact to move your servo.
       * @throws `PhidgetError`
       */
      get maxPulseWidth() {
        return this.getMaxPulseWidth();
      }
      /**
       * The minimum pulse width that `minPulseWidth` can be set to.
       *
       * See `targetPosition` for a deeper explanation of how the settings of your RC Servo controller interact to move your servo.
       * @throws `PhidgetError`
       */
      get minPulseWidthLimit() {
        return this.getMinPulseWidthLimit();
      }
      /**
       * The maximum pulse width that `maxPulseWidth` can be set to.
       *
       * See `targetPosition` for a deeper explanation of how the settings of your RC Servo controller interact to move your servo.
       * @throws `PhidgetError`
       */
      get maxPulseWidthLimit() {
        return this.getMaxPulseWidthLimit();
      }
      /**
       * When speed ramping state is enabled, the controller will take the `acceleration` and `velocityLimit` properties into account when moving the RC servo motor, usually resulting in smooth motion. If speed ramping state is not enabled, the controller will simply set the RC servo motor to the requested position.
       * @throws `PhidgetError`
       */
      get speedRampingState() {
        return this.getSpeedRampingState();
      }
      /**
       * If the RC servo motor is configured and `targetPosition` is set, the controller will continuously try to reach targeted position.
       *
       * *   The target position is bounded by `minPosition` and `maxPosition`.
       *
       * *   Using the **default settings** this position will correspond to the rotation of the servo arm in **degrees**, for many standard RC servos.
       *
       * *   If the RC servo motor is not engaged, then the position cannot be read.
       * *   The position can still be set while the RC servo motor is not engaged. Once engaged, the RC servo motor will snap to position, assuming it is not there already.
       * *   The units for `targetPosition`, `velocityLimit`, and `acceleration` are configured by scaling the internal timing (set with `minPulseWidth` and `maxPulseWidth`) to a user specified range with `minPosition` and `maxPosition`.
       *
       * ### Position and Pulse Width
       *
       * *   An RC servo motor's position is controlled using a type of **Pulse Width Modulation**, sending voltage pulses of a given time span, or **Pulse Width** to the servo.
       * *   The servo translates the **Pulse Width** of the control signal to a corresponding position of the servo arm.
       * *   Knowing this, a servo's range of motion can be thought of in terms of a `minPulseWidth` and a `maxPulseWidth` corresponding to range of pulse widths that produce the servo arm's full **range of movement**.
       *
       * *   In Phidget22, you can adjust the `minPulseWidth` and `maxPulseWidth` stored by the library to match the desired **range of movement** you expect from your servo.
       *
       * *   Since directly setting the timing of RC servo pulse widths is not very intuitive for most purpses, we map these pulse widths to a user-defied _**Minimum**_ and _**Maximum**_ **Position**.This allows you to define the servo's position in terms best suited to your application, such as degrees, fractions of a rotation, or even some measure of speed for a continuous-rotation servo.
       * *   By setting the servo's `targetPosition` to `maxPosition`, the controller will send pulses of `maxPulseWidth` to the servo.
       *     *   Similarly, `minPosition` will send pulses of `minPulseWidth` to the servo
       *     *   `maxPosition` can be set smaller than `minPosition` to invert movement of the servo, if it helps your application.
       * *   Setting a `targetPosition` will transate the position between `minPosition` and `maxPosition` to a corresponding **Pulse Width** between `minPulseWidth` and `maxPulseWidth`, in turn sending the servo arm to the desired position.
       * *   Setting `velocityLimit` and `acceleration` for your servo will limit the rate of change of the servo's position in terms of one _**UserUnit**_ per second (or /s2). Here, a _**UserUnit**_ is whatever distance is maked by the change of the `targetPosition` by **1.0**
       *
       * ### Adjusting the Servo's Limits
       *
       * *   **To tune your program to a specific servo:**
       *
       * 1.  First adjust the servo's range of motion by setting the `maxPulseWidth` and `minPulseWidth`. You can use the default values for these _(or the ones on your servo's datasheet)_ as a starting point.
       * 2.  Send the servo to `maxPosition` and `minPosition` to check the results. Repeat steps 1 and 2 as nessesarry.
       * 3.  Set the `maxPosition` and `minPosition` to match whatever numbers you find best suited to your application.
       * @throws `PhidgetError`
       */
      get targetPosition() {
        return this.getTargetPosition();
      }
      /**
       * The `torque` is a ratio of the maximum available torque.
       *
       * *   The torque is bounded by `minTorque` and `maxTorque`
       * *   Increasing the torque will increase the speed and power consumption of the RC servo motor.
       * @throws `PhidgetError`
       */
      get torque() {
        return this.getTorque();
      }
      /**
       * The minimum value that `torque` can be set to.
       *
       * *   `torque` is a ratio of the maximum available torque, therefore the minimum torque is a unitless constant.
       * @throws `PhidgetError`
       */
      get minTorque() {
        return this.getMinTorque();
      }
      /**
       * The maximum value that `torque` can be set to.
       *
       * *   `torque` is a ratio of the maximum available torque, therefore the minimum torque is a unitless constant.
       * @throws `PhidgetError`
       */
      get maxTorque() {
        return this.getMaxTorque();
      }
      /**
       * The velocity that the RC servo motor is being driven at.
       *
       * *   A negative value means the RC servo motor is moving towards a lower position.
       * *   The velocity range of the RC servo motor will be from -`velocityLimit` to +`velocityLimit`, depending on direction.
       * *   This is not the actual physical velocity of the RC servo motor.
       *
       *
       *
       * See `targetPosition` for a deeper explanation of how the settings of your RC Servo controller interact to move your servo.
       * @throws `PhidgetError`
       */
      get velocity() {
        return this.getVelocity();
      }
      /**
       * When moving, the RC servo motor velocity will be limited by this value.
       *
       * *   The velocity limit is bounded by `minVelocityLimit` and `maxVelocityLimit`.
       *
       * *   Using the **default settings** this velocity will correspond to the maximum speed of rotation of servo arm in **degrees/s**, for many standard RC servos.
       *
       * *   `speedRampingState` controls whether or not the velocity limit value is actually applied when trying to reach a target position.
       * *   The velocity range of the RC servo motor will be from -`velocityLimit` to +`velocityLimit`, depending on direction.
       * *   Note that when this value is set to 0, the RC servo motor will not move.
       * *   There is a practical limit on how fast your servo can rotate, based on the physical design of the motor.
       * *   The units for `targetPosition`, `velocityLimit`, and `acceleration` are configured by scaling the internal timing (set with `minPulseWidth` and `maxPulseWidth`) to a user specified range with `minPosition` and `maxPosition`.
       *
       *
       *
       * See `targetPosition` for a deeper explanation of how the settings of your RC Servo controller interact to move your servo.
       * @throws `PhidgetError`
       */
      get velocityLimit() {
        return this.getVelocityLimit();
      }
      /**
       * The minimum velocity `velocityLimit` can be set to.
       *
       * See `targetPosition` for a deeper explanation of how the settings of your RC Servo controller interact to move your servo.
       * @throws `PhidgetError`
       */
      get minVelocityLimit() {
        return this.getMinVelocityLimit();
      }
      /**
       * The maximum velocity `velocityLimit` can be set to. This value depends on `minPosition`/`maxPosition` and `minPulseWidth`/`maxPulseWidth`.
       *
       * See `targetPosition` for a deeper explanation of how the settings of your RC Servo controller interact to move your servo.
       * @throws `PhidgetError`
       */
      get maxVelocityLimit() {
        return this.getMaxVelocityLimit();
      }
      /**
       * The supply voltage for the RC servo motor.
       *
       * *   If your controller supports multiple RC servo motors, every motor will have the same supply voltage. It is not possible to set individual supply voltages.
       * @throws `PhidgetError`
       */
      get voltage() {
        return this.getVoltage();
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `PositionChange` / `VelocityChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getDataInterval() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 160:
          case 162:
          case 164:
          case 404:
          case 179:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.dataInterval;
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `PositionChange` / `VelocityChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * @throws `PhidgetError`
       * @param dataInterval - The data interval value
       */
      async setDataInterval(dataInterval) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: dataInterval
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMinDataInterval() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 160:
          case 162:
          case 164:
          case 404:
          case 179:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.minDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataInterval;
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMaxDataInterval() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 160:
          case 162:
          case 164:
          case 404:
          case 179:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.maxDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @returns The data rate for the channel
       * @throws `PhidgetError`
       */
      getDataRate() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 160:
          case 162:
          case 164:
          case 404:
          case 179:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return 1000.0 / this.data.dataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       * @param dataRate - The data rate for the channel
       */
      async setDataRate(dataRate) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: Math.round(1000.0 / dataRate)
        });
        bp.set({
          name: "1",
          type: "g",
          value: 1000.0 / dataRate
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMinDataRate() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 160:
          case 162:
          case 164:
          case 404:
          case 179:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.minDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataRate;
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMaxDataRate() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 160:
          case 162:
          case 164:
          case 404:
          case 179:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.maxDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataRate;
      }
      /**
       * When engaged, a RC servo motor has the ability to be positioned. When disengaged, no commands are sent to the RC servo motor.
       *
       * *   There is no position feedback to the controller, so the RC servo motor will immediately snap to the `targetPosition` after being engaged from a disengaged state.
       * *   This property is useful for relaxing a servo once it has reached a given position.
       * *   If you are concerned about tracking position accurately, you should not disengage the motor while `isMoving` is true.
       * @returns The engaged value
       * @throws `PhidgetError`
       */
      getEngaged() {
        this._assertOpen();
        if (this.data.engaged === 2) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return !!this.data.engaged;
      }
      /**
       * When engaged, a RC servo motor has the ability to be positioned. When disengaged, no commands are sent to the RC servo motor.
       *
       * *   There is no position feedback to the controller, so the RC servo motor will immediately snap to the `targetPosition` after being engaged from a disengaged state.
       * *   This property is useful for relaxing a servo once it has reached a given position.
       * *   If you are concerned about tracking position accurately, you should not disengage the motor while `isMoving` is true.
       * @throws `PhidgetError`
       * @param engaged - The engaged value
       */
      async setEngaged(engaged) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: engaged ? 1 : 0
        });
        await bp.send(this._ch, 57);
      }
      /**
       * Enables the **failsafe** feature for the channel, with the specified **failsafe time**.
       *
       * Enabling the failsafe feature starts a recurring **failsafe timer** for the channel. Once the failsafe is enabled, the timer must be reset within the specified time or the channel will enter a **failsafe state**. For RC Servo channels, this will disengage the servo. The failsafe timer can be reset by using any of the following API calls:
       *
       * *   `setAcceleration()`
       * *   `setEngaged()`
       * *   `setMinPosition()`
       * *   `setMaxPosition()`
       * *   `setMinPulseWidth()`
       * *   `setMaxPulseWidth()`
       * *   `setSpeedRampingState()`
       * *   `setVelocityLimit()`
       * *   `setVoltage()`
       * *   `resetFailsafe()`
       *
       * For more information about failsafe, visit our [Failsafe Guide](https://www.phidgets.com/docs/Failsafe_Guide).
       * @throws `PhidgetError`
       * @param failsafeTime - Failsafe timeout in milliseconds
       */
      async enableFailsafe(failsafeTime) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: failsafeTime
        });
        await bp.send(this._ch, 146);
      }
      /**
       * The minimum value that `failsafeTime` can be set to when calling `enableFailsafe()`.
       * @returns The failsafe time
       * @throws `PhidgetError`
       */
      getMinFailsafeTime() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 406:
          case 407:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.minFailsafeTime === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minFailsafeTime;
      }
      /**
       * The maximum value that `failsafeTime` can be set to when calling `enableFailsafe()`.
       * @returns The failsafe time
       * @throws `PhidgetError`
       */
      getMaxFailsafeTime() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 406:
          case 407:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.maxFailsafeTime === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxFailsafeTime;
      }
      /**
       * `isMoving` returns true if the RC servo motor is currently in motion.
       *
       * *   The controller cannot know if the RC servo motor is physically moving. When `isMoving` is false, it simply means there are no commands in the pipeline to the RC servo motor.
       * @returns The moving value
       * @throws `PhidgetError`
       */
      getIsMoving() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 4:
          case 1:
          case 2:
          case 3:
          case 8:
          case 5:
          case 6:
          case 7:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.isMoving === 2) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return !!this.data.isMoving;
      }
      /**
       * The minimum position that `targetPosition` can be set to.
       *
       * *   The units for `targetPosition`, `velocityLimit`, and `acceleration` are configured by scaling the internal timing (set with `minPulseWidth` and `maxPulseWidth`) to a user specified range with `minPosition` and `maxPosition`.
       *
       *
       *
       * See `targetPosition` for a deeper explanation of how the settings of your RC Servo controller interact to move your servo.
       * @returns The position value
       * @throws `PhidgetError`
       */
      getMinPosition() {
        this._assertOpen();
        if (this.data.minPosition === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minPosition;
      }
      /**
       * The maximum position `targetPosition` can be set to.
       *
       * *   The units for `targetPosition`, `velocityLimit`, and `acceleration` are configured by scaling the internal timing (set with `minPulseWidth` and `maxPulseWidth`) to a user specified range with `minPosition` and `maxPosition`.
       *
       *
       *
       * See `targetPosition` for a deeper explanation of how the settings of your RC Servo controller interact to move your servo.
       * @returns The position value
       * @throws `PhidgetError`
       */
      getMaxPosition() {
        this._assertOpen();
        if (this.data.maxPosition === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxPosition;
      }
      /**
       * The `minPulseWidth` represents the minimum pulse width that your RC servo motor specifies.
       *
       * *   This value can be found in the data sheet of most RC servo motors.
       * *   The units for `targetPosition`, `velocityLimit`, and `acceleration` are configured by scaling the internal timing (set with `minPulseWidth` and `maxPulseWidth`) to a user specified range with `minPosition` and `maxPosition`.
       *
       *
       *
       * See `targetPosition` for a deeper explanation of how the settings of your RC Servo controller interact to move your servo.
       * @throws `PhidgetError`
       * @param minPulseWidth - The pulse width value
       */
      async setMinPulseWidth(minPulseWidth) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: minPulseWidth
        });
        await bp.send(this._ch, 70);
      }
      /**
       * The `minPulseWidth` represents the minimum pulse width that your RC servo motor specifies.
       *
       * *   This value can be found in the data sheet of most RC servo motors.
       * *   The units for `targetPosition`, `velocityLimit`, and `acceleration` are configured by scaling the internal timing (set with `minPulseWidth` and `maxPulseWidth`) to a user specified range with `minPosition` and `maxPosition`.
       *
       *
       *
       * See `targetPosition` for a deeper explanation of how the settings of your RC Servo controller interact to move your servo.
       * @returns The pulse width value
       * @throws `PhidgetError`
       */
      getMinPulseWidth() {
        this._assertOpen();
        if (this.data.minPulseWidth === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minPulseWidth;
      }
      /**
       * The `maxPulseWidth` represents the maximum pulse width that your RC servo motor specifies.
       *
       * *   This value can be found in the data sheet of most RC servo motors.
       * *   The units for `targetPosition`, `velocityLimit`, and `acceleration` are configured by scaling the internal timing (set with `minPulseWidth` and `maxPulseWidth`) to a user specified range with `minPosition` and `maxPosition`.
       *
       *
       *
       * See `targetPosition` for a deeper explanation of how the settings of your RC Servo controller interact to move your servo.
       * @throws `PhidgetError`
       * @param maxPulseWidth - The pulse width value
       */
      async setMaxPulseWidth(maxPulseWidth) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: maxPulseWidth
        });
        await bp.send(this._ch, 69);
      }
      /**
       * The `maxPulseWidth` represents the maximum pulse width that your RC servo motor specifies.
       *
       * *   This value can be found in the data sheet of most RC servo motors.
       * *   The units for `targetPosition`, `velocityLimit`, and `acceleration` are configured by scaling the internal timing (set with `minPulseWidth` and `maxPulseWidth`) to a user specified range with `minPosition` and `maxPosition`.
       *
       *
       *
       * See `targetPosition` for a deeper explanation of how the settings of your RC Servo controller interact to move your servo.
       * @returns The pulse width value
       * @throws `PhidgetError`
       */
      getMaxPulseWidth() {
        this._assertOpen();
        if (this.data.maxPulseWidth === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxPulseWidth;
      }
      /**
       * The minimum pulse width that `minPulseWidth` can be set to.
       *
       * See `targetPosition` for a deeper explanation of how the settings of your RC Servo controller interact to move your servo.
       * @returns The pulse width value
       * @throws `PhidgetError`
       */
      getMinPulseWidthLimit() {
        this._assertOpen();
        if (this.data.minPulseWidthLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minPulseWidthLimit;
      }
      /**
       * The maximum pulse width that `maxPulseWidth` can be set to.
       *
       * See `targetPosition` for a deeper explanation of how the settings of your RC Servo controller interact to move your servo.
       * @returns The pulse width value
       * @throws `PhidgetError`
       */
      getMaxPulseWidthLimit() {
        this._assertOpen();
        if (this.data.maxPulseWidthLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxPulseWidthLimit;
      }
      /**
       * Resets the failsafe timer, if one has been set. See `enableFailsafe()` for details.
       *
       * This function will fail if no failsafe timer has been set for the channel.
       * @throws `PhidgetError`
       */
      async resetFailsafe() {
        this._assertOpen();
        const bp = new BridgePacket();
        await bp.send(this._ch, 147);
      }
      /**
       * When speed ramping state is enabled, the controller will take the `acceleration` and `velocityLimit` properties into account when moving the RC servo motor, usually resulting in smooth motion. If speed ramping state is not enabled, the controller will simply set the RC servo motor to the requested position.
       * @returns The speed ramping state value
       * @throws `PhidgetError`
       */
      getSpeedRampingState() {
        this._assertOpen();
        if (this.data.speedRampingState === 2) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return !!this.data.speedRampingState;
      }
      /**
       * When speed ramping state is enabled, the controller will take the `acceleration` and `velocityLimit` properties into account when moving the RC servo motor, usually resulting in smooth motion. If speed ramping state is not enabled, the controller will simply set the RC servo motor to the requested position.
       * @throws `PhidgetError`
       * @param speedRampingState - The speed ramping state value
       */
      async setSpeedRampingState(speedRampingState) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: speedRampingState ? 1 : 0
        });
        await bp.send(this._ch, 81);
      }
      /**
       * The `torque` is a ratio of the maximum available torque.
       *
       * *   The torque is bounded by `minTorque` and `maxTorque`
       * *   Increasing the torque will increase the speed and power consumption of the RC servo motor.
       * @returns The torque value.
       * @throws `PhidgetError`
       */
      getTorque() {
        this._assertOpen();
        throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
      }
      /**
       * The `torque` is a ratio of the maximum available torque.
       *
       * *   The torque is bounded by `minTorque` and `maxTorque`
       * *   Increasing the torque will increase the speed and power consumption of the RC servo motor.
       * @throws `PhidgetError`
       * @param torque - The torque value.
       */
      async setTorque(torque) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: torque
        });
        await bp.send(this._ch, 55);
      }
      /**
       * The minimum value that `torque` can be set to.
       *
       * *   `torque` is a ratio of the maximum available torque, therefore the minimum torque is a unitless constant.
       * @returns The torque value
       * @throws `PhidgetError`
       */
      getMinTorque() {
        this._assertOpen();
        throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
      }
      /**
       * The maximum value that `torque` can be set to.
       *
       * *   `torque` is a ratio of the maximum available torque, therefore the minimum torque is a unitless constant.
       * @returns The torque value
       * @throws `PhidgetError`
       */
      getMaxTorque() {
        this._assertOpen();
        throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
      }
      /**
       * The supply voltage for the RC servo motor.
       *
       * *   If your controller supports multiple RC servo motors, every motor will have the same supply voltage. It is not possible to set individual supply voltages.
       * @returns The voltage value
       * @throws `PhidgetError`
       */
      getVoltage() {
        this._assertOpen();
        if (this.data.voltage === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.voltage;
      }
      /**
       * The supply voltage for the RC servo motor.
       *
       * *   If your controller supports multiple RC servo motors, every motor will have the same supply voltage. It is not possible to set individual supply voltages.
       * @throws `PhidgetError`
       * @param voltage - The voltage value
       */
      async setVoltage(voltage) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: voltage
        });
        await bp.send(this._ch, 86);
      }
    }

    /** @public */
    class RCServo extends RCServoBase {
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 57:
            super._bridgeInput(bp);
            if (this.data.engaged && this.data.velocityLimit !== 0 && this.data.position !== this.data.targetPosition) this.data.isMoving = 1;
            break;
          case 85:
            super._bridgeInput(bp);
            if (this.data.engaged && this.data.velocityLimit !== 0 && this.data.position !== this.data.targetPosition) this.data.isMoving = 1;
            break;
          case 83:
            super._bridgeInput(bp);
            if (this.data.engaged && this.data.velocityLimit !== 0 && this.data.position !== this.data.targetPosition) this.data.isMoving = 1;
            break;
          case 29:
            this.data.position = bp.getNumber(0);
            if (this._isAttachedDone && this.onPositionChange) {
              try {
                this.onPositionChange(this._positionUser(this.data.position));
              } catch (err) {
                logEventException(err);
              }
            }
            break;
          case 100:
            this.data.velocity = bp.getNumber(0);
            if (this._isAttachedDone && this.onVelocityChange) {
              try {
                this.onVelocityChange(this._velocityUser(this.data.velocity));
              } catch (err) {
                logEventException(err);
              }
            }
            break;
          case 94:
            this.data.position = bp.getNumber(0);
            this.data.isMoving = 0;
            if (this._isAttachedDone && this.onTargetPositionReached) {
              try {
                this.onTargetPositionReached(this._positionUser(this.data.position));
              } catch (err) {
                logEventException(err);
              }
            }
            break;
          default:
            super._bridgeInput(bp);
            break;
        }
      }
      /** @internal */
      _positionUser(position_us) {
        if (position_us <= this.data.minPulseWidth) return this.data.minPosition;
        return this.data.minPosition + (position_us - this.data.minPulseWidth) / (this.data.maxPulseWidth - this.data.minPulseWidth) * (this.data.maxPosition - this.data.minPosition);
      }
      /** @internal */
      _positionUS(position_user) {
        if (this.data.maxPosition > this.data.minPosition) return this.data.minPulseWidth + (this.data.maxPulseWidth - this.data.minPulseWidth) * (position_user - this.data.minPosition) / (this.data.maxPosition - this.data.minPosition);
        return this.data.maxPulseWidth + (this.data.maxPulseWidth - this.data.minPulseWidth) * (position_user - this.data.maxPosition) / (this.data.maxPosition - this.data.minPosition);
      }
      /** @internal */
      _velocityUser(velocity_us) {
        return Math.abs(this.data.maxPosition - this.data.minPosition) * velocity_us / (this.data.maxPulseWidth - this.data.minPulseWidth);
      }
      /** @internal */
      _velocityUS(velocity_user) {
        return (this.data.maxPulseWidth - this.data.minPulseWidth) * velocity_user / Math.abs(this.data.maxPosition - this.data.minPosition);
      }
      /** @internal */
      _accelUser(accel_us) {
        return Math.abs(this.data.maxPosition - this.data.minPosition) * accel_us / (this.data.maxPulseWidth - this.data.minPulseWidth);
      }
      /** @internal */
      _accelUS(accel_user) {
        return (this.data.maxPulseWidth - this.data.minPulseWidth) * accel_user / Math.abs(this.data.maxPosition - this.data.minPosition);
      }
      getAcceleration() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 4:
          case 1:
          case 2:
          case 3:
          case 8:
          case 5:
          case 6:
          case 7:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.acceleration === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this._accelUser(this.data.acceleration);
      }
      getMinAcceleration() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 4:
          case 1:
          case 2:
          case 3:
          case 8:
          case 5:
          case 6:
          case 7:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.minAcceleration === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this._accelUser(this.data.minAcceleration);
      }
      getMaxAcceleration() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 4:
          case 1:
          case 2:
          case 3:
          case 8:
          case 5:
          case 6:
          case 7:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.maxAcceleration === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this._accelUser(this.data.maxAcceleration);
      }
      getPosition() {
        this._assertOpen();
        if (this.data.position === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this._positionUser(this.data.position);
      }
      setMaxPosition(maxPosition) {
        this._assertOpen();
        this.data.maxPosition = maxPosition;
      }
      setMinPosition(minPosition) {
        this._assertOpen();
        this.data.minPosition = minPosition;
      }
      getTargetPosition() {
        this._assertOpen();
        if (this.data.targetPosition === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this._positionUser(this.data.targetPosition);
      }
      getVelocity() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 4:
          case 1:
          case 2:
          case 3:
          case 8:
          case 5:
          case 6:
          case 7:
          case 405:
          case 406:
          case 407:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.velocity === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this._velocityUser(this.data.velocity);
      }
      getVelocityLimit() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 4:
          case 1:
          case 2:
          case 3:
          case 8:
          case 5:
          case 6:
          case 7:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.velocityLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this._velocityUser(this.data.velocityLimit);
      }
      getMinVelocityLimit() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 4:
          case 1:
          case 2:
          case 3:
          case 8:
          case 5:
          case 6:
          case 7:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.minVelocityLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this._velocityUser(this.data.minVelocityLimit);
      }
      getMaxVelocityLimit() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 4:
          case 1:
          case 2:
          case 3:
          case 8:
          case 5:
          case 6:
          case 7:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.maxVelocityLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this._velocityUser(this.data.maxVelocityLimit);
      }
      async setAcceleration(acceleration) {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 4:
          case 1:
          case 2:
          case 3:
          case 8:
          case 5:
          case 6:
          case 7:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        acceleration = this._accelUS(acceleration);
        if (acceleration < this.data.minAcceleration || acceleration > this.data.maxAcceleration) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Value must be in range: " + this.minAcceleration + " - " + this.maxAcceleration + ".");
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: acceleration
        });
        await bp.send(this._ch, 40);
      }
      async setTargetPosition(targetPosition) {
        this._assertOpen();
        targetPosition = this._positionUS(targetPosition);
        if (targetPosition < this.data.minPulseWidth || targetPosition > this.data.maxPulseWidth) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Value must be in range: " + this.minPosition + " - " + this.maxPosition + ".");
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: targetPosition
        });
        await bp.send(this._ch, 83);
      }
      async setVelocityLimit(velocityLimit) {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 4:
          case 1:
          case 2:
          case 3:
          case 8:
          case 5:
          case 6:
          case 7:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        velocityLimit = this._velocityUS(velocityLimit);
        if (velocityLimit < this.data.minVelocityLimit || velocityLimit > this.data.maxVelocityLimit) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Value must be in range: " + this.minVelocityLimit + " - " + this.maxVelocityLimit + ".");
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: velocityLimit
        });
        await bp.send(this._ch, 85);
      }
    }

    /**
     * The Resistance Input class measures the resistance of a circuit connected to the Phidget, which is used to read resistance-based sensors such as platinum RTDs.
     * @public
     */
    class ResistanceInputBase extends PhidgetChannel {
      /** @internal */
      data;
      onResistanceChange = null;
      /** @internal */
      _gotResistanceChangeErrorEvent;
      constructor(ch) {
        super(ch);
        this._class = exports.ChannelClass.RESISTANCE_INPUT;
        this.name = "ResistanceInput";
        this.data = this._initData();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 54:
            if (bp.entryCount > 1) this.data.dataInterval = bp.entries[1].v;else this.data.dataInterval = bp.entries[0].v;
            this._FIREPropertyChange('DataInterval', bp);
            this._FIREPropertyChange('DataRate', bp);
            break;
          case 46:
            this.data.resistanceChangeTrigger = bp.entries[0].v;
            this._FIREPropertyChange('ResistanceChangeTrigger', bp);
            break;
          case 77:
            this.data.RTDWireSetup = bp.entries[0].v;
            this._FIREPropertyChange('RTDWireSetup', bp);
            break;
          case 36:
            {
              this.data.resistance = bp.entries[0].v;
              if (this._isAttachedDone && this.onResistanceChange) {
                try {
                  this.onResistanceChange(this.data.resistance);
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          default:
            throw new PhidgetError(exports.ErrorCode.INVALID_PACKET, "Unsupported bridge packet: 0x" + bp.vpkt.toString(16));
        }
      }
      /** @internal */
      _initData() {
        return {
          dataInterval: 1e+300,
          maxDataInterval: 4294967295,
          minDataRate: 1e+300,
          maxDataRate: 1e+300,
          maxResistance: 1e+300,
          maxResistanceChangeTrigger: 1e+300,
          minDataInterval: 4294967295,
          minResistance: 1e+300,
          minResistanceChangeTrigger: 1e+300,
          resistance: 1e+300,
          resistanceChangeTrigger: 1e+300,
          RTDWireSetup: 2147483647
        };
      }
      /** @internal */
      _initAfterOpen() {}
      /** @internal */
      async _setDefaults() {}
      /** @internal */
      _hasInitialState() {
        return true;
      }
      /** @internal */
      _fireInitialEvents() {}
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `ResistanceChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between `ResistanceChange` events can also be affected by the `resistanceChangeTrigger`.
       * @throws `PhidgetError`
       */
      get dataInterval() {
        return this.getDataInterval();
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get minDataInterval() {
        return this.getMinDataInterval();
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataInterval() {
        return this.getMaxDataInterval();
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       */
      get dataRate() {
        return this.getDataRate();
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get minDataRate() {
        return this.getMinDataRate();
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataRate() {
        return this.getMaxDataRate();
      }
      /**
       * The most recent resistance value that the channel has reported.
       *
       * *   This value will always be between `minResistance` and `maxResistance`.
       * *   The `resistance` value will change when the device is also being used as a temperature sensor. This is a side effect of increasing accuracy on the temperature channel.
       * @throws `PhidgetError`
       */
      get resistance() {
        return this.getResistance();
      }
      /**
       * The minimum value the `ResistanceChange` event will report.
       *
       * *   When the device is also being used as a TemperatureSensor the `minResistance` and `maxResistance` will not represent the true input range. This is a side effect of increasing accuracy on the temperature channel.
       * @throws `PhidgetError`
       */
      get minResistance() {
        return this.getMinResistance();
      }
      /**
       * The maximum value the `ResistanceChange` event will report.
       * @throws `PhidgetError`
       */
      get maxResistance() {
        return this.getMaxResistance();
      }
      /**
       * The channel will not issue a `ResistanceChange` event until the resistance value has changed by the amount specified by the `resistanceChangeTrigger`.
       *
       * *   Setting the `resistanceChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @throws `PhidgetError`
       */
      get resistanceChangeTrigger() {
        return this.getResistanceChangeTrigger();
      }
      /**
       * The minimum value that the `resistanceChangeTrigger` can be set to.
       * @throws `PhidgetError`
       */
      get minResistanceChangeTrigger() {
        return this.getMinResistanceChangeTrigger();
      }
      /**
       * The maximum value that `resistanceChangeTrigger` can be set to.
       * @throws `PhidgetError`
       */
      get maxResistanceChangeTrigger() {
        return this.getMaxResistanceChangeTrigger();
      }
      /**
       * Select the RTD wiring configuration.
       *
       * *   More information about RTD wiring can be found in the user guide.
       * @throws `PhidgetError`
       */
      get RTDWireSetup() {
        return this.getRTDWireSetup();
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `ResistanceChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between `ResistanceChange` events can also be affected by the `resistanceChangeTrigger`.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getDataInterval() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.dataInterval;
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `ResistanceChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between `ResistanceChange` events can also be affected by the `resistanceChangeTrigger`.
       * @throws `PhidgetError`
       * @param dataInterval - The data interval value
       */
      async setDataInterval(dataInterval) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: dataInterval
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMinDataInterval() {
        this._assertOpen();
        if (this.data.minDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataInterval;
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMaxDataInterval() {
        this._assertOpen();
        if (this.data.maxDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @returns The data rate for the channel
       * @throws `PhidgetError`
       */
      getDataRate() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return 1000.0 / this.data.dataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       * @param dataRate - The data rate for the channel
       */
      async setDataRate(dataRate) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: Math.round(1000.0 / dataRate)
        });
        bp.set({
          name: "1",
          type: "g",
          value: 1000.0 / dataRate
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMinDataRate() {
        this._assertOpen();
        if (this.data.minDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataRate;
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMaxDataRate() {
        this._assertOpen();
        if (this.data.maxDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataRate;
      }
      /**
       * The most recent resistance value that the channel has reported.
       *
       * *   This value will always be between `minResistance` and `maxResistance`.
       * *   The `resistance` value will change when the device is also being used as a temperature sensor. This is a side effect of increasing accuracy on the temperature channel.
       * @returns The resistance value
       * @throws `PhidgetError`
       */
      getResistance() {
        this._assertOpen();
        if (this.data.resistance === 1e+300 || Number.isNaN(this.data.resistance)) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        if (this.data.resistance > this.data.maxResistance) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE_HIGH);
        if (this.data.resistance < this.data.minResistance) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE_LOW);
        return this.data.resistance;
      }
      /**
       * The minimum value the `ResistanceChange` event will report.
       *
       * *   When the device is also being used as a TemperatureSensor the `minResistance` and `maxResistance` will not represent the true input range. This is a side effect of increasing accuracy on the temperature channel.
       * @returns The minimum resistance
       * @throws `PhidgetError`
       */
      getMinResistance() {
        this._assertOpen();
        if (this.data.minResistance === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minResistance;
      }
      /**
       * The maximum value the `ResistanceChange` event will report.
       * @returns The resistance value
       * @throws `PhidgetError`
       */
      getMaxResistance() {
        this._assertOpen();
        if (this.data.maxResistance === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxResistance;
      }
      /**
       * The channel will not issue a `ResistanceChange` event until the resistance value has changed by the amount specified by the `resistanceChangeTrigger`.
       *
       * *   Setting the `resistanceChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getResistanceChangeTrigger() {
        this._assertOpen();
        if (this.data.resistanceChangeTrigger === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.resistanceChangeTrigger;
      }
      /**
       * The channel will not issue a `ResistanceChange` event until the resistance value has changed by the amount specified by the `resistanceChangeTrigger`.
       *
       * *   Setting the `resistanceChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @throws `PhidgetError`
       * @param resistanceChangeTrigger - The change trigger value
       */
      async setResistanceChangeTrigger(resistanceChangeTrigger) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: resistanceChangeTrigger
        });
        await bp.send(this._ch, 46);
      }
      /**
       * The minimum value that the `resistanceChangeTrigger` can be set to.
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getMinResistanceChangeTrigger() {
        this._assertOpen();
        if (this.data.minResistanceChangeTrigger === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minResistanceChangeTrigger;
      }
      /**
       * The maximum value that `resistanceChangeTrigger` can be set to.
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getMaxResistanceChangeTrigger() {
        this._assertOpen();
        if (this.data.maxResistanceChangeTrigger === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxResistanceChangeTrigger;
      }
      /**
       * Select the RTD wiring configuration.
       *
       * *   More information about RTD wiring can be found in the user guide.
       * @returns Wire setup value
       * @throws `PhidgetError`
       */
      getRTDWireSetup() {
        this._assertOpen();
        if (this.data.RTDWireSetup === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.RTDWireSetup;
      }
      /**
       * Select the RTD wiring configuration.
       *
       * *   More information about RTD wiring can be found in the user guide.
       * @throws `PhidgetError`
       * @param RTDWireSetup - Wire setup value
       */
      async setRTDWireSetup(RTDWireSetup) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: RTDWireSetup
        });
        await bp.send(this._ch, 77);
      }
    }

    /** @public */
    class ResistanceInput extends ResistanceInputBase {
      /** @internal */
      _errorHandler(code) {
        switch (code) {
          case exports.ErrorEventCode.SATURATION:
            this.data.resistance = 1e+300;
            this._gotResistanceChangeErrorEvent = true;
            break;
        }
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 180:
            this.data.RTDWireSetup = bp.entries[0].v;
            this._FIREPropertyChange('RTDWireSetup', bp);
            break;
          default:
            super._bridgeInput(bp);
            break;
        }
      }
    }

    /**
     * The RFID class provides methods for Phidget RFID boards to read and write (if writing is supported) to RFID tags.
     * @public
     */
    class RFIDBase extends PhidgetChannel {
      /** @internal */
      data;
      onTag = null;
      /** @internal */
      _gotTagErrorEvent;
      onTagLost = null;
      /** @internal */
      _gotTagLostErrorEvent;
      constructor(ch) {
        super(ch);
        this._class = exports.ChannelClass.RFID;
        this.name = "RFID";
        this.data = this._initData();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 41:
            this.data.antennaEnabled = bp.entries[0].v;
            this._FIREPropertyChange('AntennaEnabled', bp);
            break;
          case 103:
            break;
          case 201:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.INVALID_PACKET, "Unsupported bridge packet: 0x" + bp.vpkt.toString(16));
        }
      }
      /** @internal */
      _initData() {
        return {
          lastTagString: null,
          lastTagProtocol: 0,
          lastTagType: 0,
          lastTagMemorySize: 0,
          lastTagUserMemorySize: 0,
          lastTagNDEFMemorySize: 0,
          antennaEnabled: 2,
          tagPresent: 2
        };
      }
      /** @internal */
      _initAfterOpen() {}
      /** @internal */
      async _setDefaults() {}
      /** @internal */
      _hasInitialState() {
        return true;
      }
      /** @internal */
      _fireInitialEvents() {}
      /**
       * The on/off state of the antenna.
       *
       * *   You can turn the antenna off to save power.
       * *   You must turn the antenna on in order to detect and read RFID tags.
       * @throws `PhidgetError`
       */
      get antennaEnabled() {
        return this.getAntennaEnabled();
      }
      /**
       * This property is true if a compatibile RFID tag is detected by the reader.
       *
       * *   `TagPresent` will remain true until the tag is out of range and can no longer be interacted with.
       * @throws `PhidgetError`
       */
      get tagPresent() {
        return this.getTagPresent();
      }
      /**
       * The on/off state of the antenna.
       *
       * *   You can turn the antenna off to save power.
       * *   You must turn the antenna on in order to detect and read RFID tags.
       * @returns The state of the antenna
       * @throws `PhidgetError`
       */
      getAntennaEnabled() {
        this._assertOpen();
        if (this.data.antennaEnabled === 2) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return !!this.data.antennaEnabled;
      }
      /**
       * The on/off state of the antenna.
       *
       * *   You can turn the antenna off to save power.
       * *   You must turn the antenna on in order to detect and read RFID tags.
       * @throws `PhidgetError`
       * @param antennaEnabled - The state of the antenna
       */
      async setAntennaEnabled(antennaEnabled) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: antennaEnabled ? 1 : 0
        });
        await bp.send(this._ch, 41);
      }
      /**
       * This property is true if a compatibile RFID tag is detected by the reader.
       *
       * *   `TagPresent` will remain true until the tag is out of range and can no longer be interacted with.
       * @returns Tag is in range
       * @throws `PhidgetError`
       */
      getTagPresent() {
        this._assertOpen();
        if (this.data.tagPresent === 2) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return !!this.data.tagPresent;
      }
    }

    /** @internal */
    new TextEncoder();
    /** @internal */
    new TextDecoder('utf-8');
    /** @internal */
    new TextDecoder('utf-16le');
    /** @internal */
    new TextDecoder('utf-16be');

    /** @public */
    class RFID extends RFIDBase {
      /** @internal */
      _transactionLock;
      /** @internal */
      _private;
      constructor(ch) {
        super(ch);
        this._transactionLock = new PhidgetLock();
      }
      /** @internal */
      _initAfterOpen() {
        super._initAfterOpen();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 92:
            {
              this.data.tagPresent = 1;
              const tag = bp.getString(0);
              const protocol = bp.getNumber(1);
              this.data.lastTagString = tag;
              this.data.lastTagProtocol = protocol;
              if (bp.entryCount > 2) {
                this.data.lastTagMemorySize = bp.getNumber(2);
                this.data.lastTagUserMemorySize = bp.getNumber(3);
                this.data.lastTagNDEFMemorySize = bp.getNumber(4);
                this.data.lastTagType = bp.getNumber(5);
              }
              if (this._isAttachedDone && this.onTag) {
                try {
                  this.onTag(tag, protocol);
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          case 93:
            {
              this.data.tagPresent = 0;
              const tag = bp.getString(0);
              const protocol = bp.getNumber(1);
              if (this._isAttachedDone && this.onTagLost) {
                try {
                  this.onTagLost(tag, protocol);
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          case 41:
            if (this.data.tagPresent === 2) this.data.tagPresent = 0;
            super._bridgeInput(bp);
            break;
          default:
            super._bridgeInput(bp);
            break;
        }
      }
      async write(tagString, protocol, lockTag, chipset) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "s",
          value: tagString
        });
        if (!supportedRFIDProtocol(this._ch, protocol)) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Specified RFIDProtocol is unsupported by this device.");
        bp.set({
          name: "1",
          type: "d",
          value: protocol
        });
        if (lockTag !== false && lockTag !== true) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Value must be a boolean.");
        bp.set({
          name: "2",
          type: "d",
          value: lockTag ? 1 : 0
        });
        if (typeof chipset !== 'undefined') {
          if (!supportedRFIDChipset(this._ch, chipset)) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Specified RFIDChipset is unsupported by this device.");
          bp.set({
            name: "3",
            type: "d",
            value: chipset
          });
          await bp.send(this._ch, 201);
        } else await bp.send(this._ch, 103);
      }
      getLastTag() {
        this._assertOpen();
        if (!this.data.lastTagString) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return {
          tagString: this.data.lastTagString,
          protocol: this.data.lastTagProtocol
        };
      }
    }

    /**
     * The Sound Sensor class gathers data from the sound sensor on a Phidget board.
     *
     * If you're using a simple 0-5V sensor that does not have its own firmware, use the VoltageInput or VoltageRatioInput class instead, as specified for your device.
     * @public
     */
    class SoundSensorBase extends PhidgetChannel {
      /** @internal */
      data;
      onSPLChange = null;
      /** @internal */
      _gotSPLChangeErrorEvent;
      constructor(ch) {
        super(ch);
        this._class = exports.ChannelClass.SOUND_SENSOR;
        this.name = "SoundSensor";
        this.data = this._initData();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 54:
            if (bp.entryCount > 1) this.data.dataInterval = bp.entries[1].v;else this.data.dataInterval = bp.entries[0].v;
            this._FIREPropertyChange('DataInterval', bp);
            this._FIREPropertyChange('DataRate', bp);
            break;
          case 46:
            this.data.SPLChangeTrigger = bp.entries[0].v;
            this._FIREPropertyChange('SPLChangeTrigger', bp);
            break;
          case 116:
            this.data.SPLRange = bp.entries[0].v;
            this._FIREPropertyChange('SPLRange', bp);
            break;
          case 11:
            {
              this.data.dB = bp.entries[0].v;
              this.data.dBA = bp.entries[1].v;
              this.data.dBC = bp.entries[2].v;
              this.data.octaves = bp.entries[3].v;
              if (this._isAttachedDone && this.onSPLChange) {
                try {
                  this.onSPLChange(this.data.dB, this.data.dBA, this.data.dBC, this.data.octaves);
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          default:
            throw new PhidgetError(exports.ErrorCode.INVALID_PACKET, "Unsupported bridge packet: 0x" + bp.vpkt.toString(16));
        }
      }
      /** @internal */
      _initData() {
        return {
          lastdB: 0,
          dataInterval: 1e+300,
          maxDataInterval: 4294967295,
          minDataRate: 1e+300,
          maxDataRate: 1e+300,
          maxdB: 1e+300,
          maxSPLChangeTrigger: 1e+300,
          minDataInterval: 4294967295,
          noiseFloor: 1e+300,
          minSPLChangeTrigger: 1e+300,
          dB: 1e+300,
          dBA: 1e+300,
          dBC: 1e+300,
          octaves: [1e+300, 1e+300, 1e+300, 1e+300, 1e+300, 1e+300, 1e+300, 1e+300, 1e+300, 1e+300],
          SPLRange: 2147483647,
          SPLChangeTrigger: 1e+300
        };
      }
      /** @internal */
      _initAfterOpen() {}
      /** @internal */
      async _setDefaults() {}
      /** @internal */
      _hasInitialState() {
        return true;
      }
      /** @internal */
      _fireInitialEvents() {}
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `SPLChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between `SPLChange` events can also be affected by the `SPLChangeTrigger`.
       * @throws `PhidgetError`
       */
      get dataInterval() {
        return this.getDataInterval();
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get minDataInterval() {
        return this.getMinDataInterval();
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataInterval() {
        return this.getMaxDataInterval();
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       */
      get dataRate() {
        return this.getDataRate();
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get minDataRate() {
        return this.getMinDataRate();
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataRate() {
        return this.getMaxDataRate();
      }
      /**
       * The most recent dB SPL value that has been calculated.
       *
       * *   This value is bounded by `maxdB`.
       * @throws `PhidgetError`
       */
      get dB() {
        return this.getdB();
      }
      /**
       * The most recent dBA SPL value that has been calculated.
       *
       * *   The dBA SPL value is calculated by applying a A-weighted filter to the `octaves` data.
       * @throws `PhidgetError`
       */
      get dBA() {
        return this.getdBA();
      }
      /**
       * The most recent dBC SPL value that has been calculated.
       *
       * *   The dBC SPL value is calculated by applying a C-weighted filter to the `octaves` data.
       * @throws `PhidgetError`
       */
      get dBC() {
        return this.getdBC();
      }
      /**
       * The maximum value the `SPLChange` event will report.
       * @throws `PhidgetError`
       */
      get maxdB() {
        return this.getMaxdB();
      }
      /**
       * The minimum SPL value that the channel can accurately measure.
       *
       * *   Input SPLs below this level will not produce an output from the microphone.
       * @throws `PhidgetError`
       */
      get noiseFloor() {
        return this.getNoiseFloor();
      }
      /**
       * The unweighted value of each frequency band.
       *
       * *   The following frequency bands are represented:
       *
       * *   octaves\[0\] = 31.5 Hz
       * *   octaves\[1\] = 63 Hz
       * *   octaves\[2\] = 125 Hz
       * *   octaves\[3\] = 250 Hz
       * *   octaves\[4\] = 500 Hz
       * *   octaves\[5\] = 1 kHz
       * *   octaves\[6\] = 2 kHz
       * *   octaves\[7\] = 4 kHz
       * *   octaves\[8\] = 8 kHz
       * *   octaves\[9\] = 16 kHz
       * @throws `PhidgetError`
       */
      get octaves() {
        return this.getOctaves();
      }
      /**
       * The channel will not issue a `SPLChange` event until the `dB` value has changed by the amount specified by the `SPLChangeTrigger`.
       *
       * *   Setting the `SPLChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @throws `PhidgetError`
       */
      get SPLChangeTrigger() {
        return this.getSPLChangeTrigger();
      }
      /**
       * The minimum value that `SPLChangeTrigger` can be set to.
       * @throws `PhidgetError`
       */
      get minSPLChangeTrigger() {
        return this.getMinSPLChangeTrigger();
      }
      /**
       * The maximum value that `SPLChangeTrigger` can be set to.
       * @throws `PhidgetError`
       */
      get maxSPLChangeTrigger() {
        return this.getMaxSPLChangeTrigger();
      }
      /**
       * When selecting a range, first decide how sensitive you want the microphone to be. Select a smaller range when you want more sensitivity from the microphone.
       *
       * *   If a `Saturation` event occurrs, increase the range.
       * @throws `PhidgetError`
       */
      get SPLRange() {
        return this.getSPLRange();
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `SPLChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between `SPLChange` events can also be affected by the `SPLChangeTrigger`.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getDataInterval() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.dataInterval;
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `SPLChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between `SPLChange` events can also be affected by the `SPLChangeTrigger`.
       * @throws `PhidgetError`
       * @param dataInterval - The data interval value
       */
      async setDataInterval(dataInterval) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: dataInterval
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMinDataInterval() {
        this._assertOpen();
        if (this.data.minDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataInterval;
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMaxDataInterval() {
        this._assertOpen();
        if (this.data.maxDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @returns The data rate for the channel
       * @throws `PhidgetError`
       */
      getDataRate() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return 1000.0 / this.data.dataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       * @param dataRate - The data rate for the channel
       */
      async setDataRate(dataRate) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: Math.round(1000.0 / dataRate)
        });
        bp.set({
          name: "1",
          type: "g",
          value: 1000.0 / dataRate
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMinDataRate() {
        this._assertOpen();
        if (this.data.minDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataRate;
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMaxDataRate() {
        this._assertOpen();
        if (this.data.maxDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataRate;
      }
      /**
       * The most recent dB SPL value that has been calculated.
       *
       * *   This value is bounded by `maxdB`.
       * @returns The dB value
       * @throws `PhidgetError`
       */
      getdB() {
        this._assertOpen();
        if (this.data.dB === 1e+300 || Number.isNaN(this.data.dB)) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        if (this.data.dB > this.data.maxdB) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE_HIGH);
        return this.data.dB;
      }
      /**
       * The most recent dBA SPL value that has been calculated.
       *
       * *   The dBA SPL value is calculated by applying a A-weighted filter to the `octaves` data.
       * @returns The dBA value
       * @throws `PhidgetError`
       */
      getdBA() {
        this._assertOpen();
        if (this.data.dBA === 1e+300 || Number.isNaN(this.data.dBA)) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.dBA;
      }
      /**
       * The most recent dBC SPL value that has been calculated.
       *
       * *   The dBC SPL value is calculated by applying a C-weighted filter to the `octaves` data.
       * @returns The dBC value
       * @throws `PhidgetError`
       */
      getdBC() {
        this._assertOpen();
        if (this.data.dBC === 1e+300 || Number.isNaN(this.data.dBC)) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.dBC;
      }
      /**
       * The maximum value the `SPLChange` event will report.
       * @returns The dB value
       * @throws `PhidgetError`
       */
      getMaxdB() {
        this._assertOpen();
        if (this.data.maxdB === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxdB;
      }
      /**
       * The minimum SPL value that the channel can accurately measure.
       *
       * *   Input SPLs below this level will not produce an output from the microphone.
       * @returns The noise floor value.
       * @throws `PhidgetError`
       */
      getNoiseFloor() {
        this._assertOpen();
        if (this.data.noiseFloor === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.noiseFloor;
      }
      /**
       * The unweighted value of each frequency band.
       *
       * *   The following frequency bands are represented:
       *
       * *   octaves\[0\] = 31.5 Hz
       * *   octaves\[1\] = 63 Hz
       * *   octaves\[2\] = 125 Hz
       * *   octaves\[3\] = 250 Hz
       * *   octaves\[4\] = 500 Hz
       * *   octaves\[5\] = 1 kHz
       * *   octaves\[6\] = 2 kHz
       * *   octaves\[7\] = 4 kHz
       * *   octaves\[8\] = 8 kHz
       * *   octaves\[9\] = 16 kHz
       * @returns The octave values
       * @throws `PhidgetError`
       */
      getOctaves() {
        var _context;
        this._assertOpen();
        if (_includesInstanceProperty(_context = this.data.octaves).call(_context, 1e+300)) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.octaves;
      }
      /**
       * The channel will not issue a `SPLChange` event until the `dB` value has changed by the amount specified by the `SPLChangeTrigger`.
       *
       * *   Setting the `SPLChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getSPLChangeTrigger() {
        this._assertOpen();
        if (this.data.SPLChangeTrigger === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.SPLChangeTrigger;
      }
      /**
       * The channel will not issue a `SPLChange` event until the `dB` value has changed by the amount specified by the `SPLChangeTrigger`.
       *
       * *   Setting the `SPLChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @throws `PhidgetError`
       * @param SPLChangeTrigger - The change trigger value
       */
      async setSPLChangeTrigger(SPLChangeTrigger) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: SPLChangeTrigger
        });
        await bp.send(this._ch, 46);
      }
      /**
       * The minimum value that `SPLChangeTrigger` can be set to.
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getMinSPLChangeTrigger() {
        this._assertOpen();
        if (this.data.minSPLChangeTrigger === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minSPLChangeTrigger;
      }
      /**
       * The maximum value that `SPLChangeTrigger` can be set to.
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getMaxSPLChangeTrigger() {
        this._assertOpen();
        if (this.data.maxSPLChangeTrigger === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxSPLChangeTrigger;
      }
      /**
       * When selecting a range, first decide how sensitive you want the microphone to be. Select a smaller range when you want more sensitivity from the microphone.
       *
       * *   If a `Saturation` event occurrs, increase the range.
       * @returns The range value.
       * @throws `PhidgetError`
       */
      getSPLRange() {
        this._assertOpen();
        if (this.data.SPLRange === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.SPLRange;
      }
      /**
       * When selecting a range, first decide how sensitive you want the microphone to be. Select a smaller range when you want more sensitivity from the microphone.
       *
       * *   If a `Saturation` event occurrs, increase the range.
       * @throws `PhidgetError`
       * @param SPLRange - The range value.
       */
      async setSPLRange(SPLRange) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: SPLRange
        });
        await bp.send(this._ch, 116);
      }
    }

    /** @public */
    class SoundSensor extends SoundSensorBase {
      /** @internal */
      _hasInitialState() {
        if (this.data.dB == 1e+300) return false;
        return true;
      }
      /** @internal */
      _fireInitialEvents() {
        if (this.data.dB != 1e+300) {
          if (this.onSPLChange) {
            try {
              this.onSPLChange(this.data.dB, this.data.dBA, this.data.dBC, this.data.octaves);
            } catch (err) {
              logEventException(err);
            }
          }
        }
      }
    }

    /**
     * The Spatial class simultaneously gathers data from the acceleromter, gyroscope and magnetometer on a Phidget board.
     *
     * You can also use the individual classes for these sensors if you want to handle the data in separate events.
     * @public
     */
    class SpatialBase extends PhidgetChannel {
      /** @internal */
      data;
      onSpatialData = null;
      /** @internal */
      _gotSpatialDataErrorEvent;
      onAlgorithmData = null;
      /** @internal */
      _gotAlgorithmDataErrorEvent;
      constructor(ch) {
        super(ch);
        this._class = exports.ChannelClass.SPATIAL;
        this.name = "Spatial";
        this.data = this._initData();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 174:
            break;
          case 149:
            this.data.algorithm = bp.entries[0].v;
            this._FIREPropertyChange('Algorithm', bp);
            break;
          case 151:
            this.data.algorithmMagnetometerGain = bp.entries[0].v;
            this._FIREPropertyChange('AlgorithmMagnetometerGain', bp);
            break;
          case 54:
            if (bp.entryCount > 1) this.data.dataInterval = bp.entries[1].v;else this.data.dataInterval = bp.entries[0].v;
            this._FIREPropertyChange('DataInterval', bp);
            this._FIREPropertyChange('DataRate', bp);
            break;
          case 170:
            this.data.heatingEnabled = bp.entries[0].v;
            this._FIREPropertyChange('HeatingEnabled', bp);
            break;
          case 50:
            break;
          case 145:
            this.data.precision = bp.entries[0].v;
            this._FIREPropertyChange('Precision', bp);
            break;
          case 35:
            break;
          case 37:
            break;
          case 150:
            break;
          case 106:
            break;
          case 89:
            {
              if (this._isAttachedDone && this.onSpatialData) {
                try {
                  this.onSpatialData(bp.entries[0].v, bp.entries[1].v, bp.entries[2].v, bp.entries[3].v);
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          default:
            throw new PhidgetError(exports.ErrorCode.INVALID_PACKET, "Unsupported bridge packet: 0x" + bp.vpkt.toString(16));
        }
      }
      /** @internal */
      _initData() {
        return {
          dataInterval: 1e+300,
          maxDataInterval: 4294967295,
          minDataInterval: 4294967295,
          minDataRate: 1e+300,
          maxDataRate: 1e+300,
          precision: 2147483647,
          algorithm: 2147483647,
          algorithmMagnetometerGain: 1e+300,
          maxAcceleration: [1e+300, 1e+300, 1e+300],
          minAcceleration: [1e+300, 1e+300, 1e+300],
          maxAngularRate: [1e+300, 1e+300, 1e+300],
          minAngularRate: [1e+300, 1e+300, 1e+300],
          maxMagneticField: [1e+300, 1e+300, 1e+300],
          minMagneticField: [1e+300, 1e+300, 1e+300],
          heatingEnabled: 2,
          quaternion: null,
          eulerAngles: null
        };
      }
      /** @internal */
      _initAfterOpen() {}
      /** @internal */
      async _setDefaults() {}
      /** @internal */
      _hasInitialState() {
        return true;
      }
      /** @internal */
      _fireInitialEvents() {}
      /**
       * The minimum acceleration the sensor will measure.
       * @throws `PhidgetError`
       */
      get minAcceleration() {
        return this.getMinAcceleration();
      }
      /**
       * The maximum acceleration the sensor will measure.
       * @throws `PhidgetError`
       */
      get maxAcceleration() {
        return this.getMaxAcceleration();
      }
      /**
       * Selects the IMU/AHRS algorithm.
       * @throws `PhidgetError`
       */
      get algorithm() {
        return this.getAlgorithm();
      }
      /**
       * Sets the gain for the magnetometer in the AHRS algorithm. Lower gains reduce sensor noise while slowing response time.
       * @throws `PhidgetError`
       */
      get algorithmMagnetometerGain() {
        return this.getAlgorithmMagnetometerGain();
      }
      /**
       * The minimum angular rate the sensor will measure.
       * @throws `PhidgetError`
       */
      get minAngularRate() {
        return this.getMinAngularRate();
      }
      /**
       * The maximum angular rate the sensor will measure.
       * @throws `PhidgetError`
       */
      get maxAngularRate() {
        return this.getMaxAngularRate();
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `SpatialData` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * @throws `PhidgetError`
       */
      get dataInterval() {
        return this.getDataInterval();
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get minDataInterval() {
        return this.getMinDataInterval();
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataInterval() {
        return this.getMaxDataInterval();
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       */
      get dataRate() {
        return this.getDataRate();
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get minDataRate() {
        return this.getMinDataRate();
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataRate() {
        return this.getMaxDataRate();
      }
      /**
       * Gets the latest device orientation in the form of Euler angles. (Pitch, roll, and yaw)
       * @throws `PhidgetError`
       */
      get eulerAngles() {
        return this.getEulerAngles();
      }
      /**
       * Set to TRUE to enable the temperature stabilization feature of this device. This enables on-board heating elements to bring the board up to a known temperature to minimize ambient temperature effects on the sensor's reading. You can leave this setting FALSE to conserve power consumption.
       *
       * If you enable heating, it is strongly recommended to keep the board in its enclosure to keep it insulated from moving air.
       *
       * This property is shared by any and all spatial-related objects on this device (Accelerometer, Gyroscope, Magnetometer, Spatial)
       * @throws `PhidgetError`
       */
      get heatingEnabled() {
        return this.getHeatingEnabled();
      }
      /**
       * The minimum field strength the sensor will measure.
       * @throws `PhidgetError`
       */
      get minMagneticField() {
        return this.getMinMagneticField();
      }
      /**
       * The maximum field strength the sensor will measure.
       * @throws `PhidgetError`
       */
      get maxMagneticField() {
        return this.getMaxMagneticField();
      }
      /**
       * Selects between high/low precision sensing chips.
       * @throws `PhidgetError`
       * @internal
       */
      get precision() {
        return this.getPrecision();
      }
      /**
       * Gets the latest AHRS/IMU quaternion sent from the device.
       * @throws `PhidgetError`
       */
      get quaternion() {
        return this.getQuaternion();
      }
      /**
       * The minimum acceleration the sensor will measure.
       * @returns The minimum acceleration value
       * @throws `PhidgetError`
       */
      getMinAcceleration() {
        var _context;
        this._assertOpen();
        if (_includesInstanceProperty(_context = this.data.minAcceleration).call(_context, 1e+300)) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minAcceleration;
      }
      /**
       * The maximum acceleration the sensor will measure.
       * @returns The maximum acceleration values
       * @throws `PhidgetError`
       */
      getMaxAcceleration() {
        var _context2;
        this._assertOpen();
        if (_includesInstanceProperty(_context2 = this.data.maxAcceleration).call(_context2, 1e+300)) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxAcceleration;
      }
      /**
       * Calibrate your device for the environment it will be used in.
       *
       * *   Setting these parameters will allow you to tune the AHRS algorithm on the device to your specific application.
       * @throws `PhidgetError`
       * @param angularVelocityThreshold - The maximum angular velocity reading where the device is assumed to be "at rest"
       * @param angularVelocityDeltaThreshold - The acceptable amount of change in angular velocity between measurements before movement is assumed.
       * @param accelerationThreshold - The maximum acceleration applied to the device (minus gravity) where it is assumed to be "at rest". This is also the maximum acceleration allowable before the device stops correcting to the acceleration vector.
       * @param magTime - The time it will take to correct the heading 95% of the way to aligning with the compass (in seconds),up to 15 degrees of error. Beyond 15 degrees, this is the time it will take for the bearing to move 45 degrees towards the compass reading. Remember you can zero the algorithm at any time to instantly realign the spatial with acceleration and magnetic field vectors regardless of magnitude.
       * @param accelTime - The time it will take to correct the pitch and roll 95% of the way to aligning with the accelerometer (in seconds).
       * @param biasTime - The time it will take to have the gyro biases settle to within 95% of the measured steady state (in seconds).
       */
      async setAHRSParameters(angularVelocityThreshold, angularVelocityDeltaThreshold, accelerationThreshold, magTime, accelTime, biasTime) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: angularVelocityThreshold
        });
        bp.set({
          name: "1",
          type: "g",
          value: angularVelocityDeltaThreshold
        });
        bp.set({
          name: "2",
          type: "g",
          value: accelerationThreshold
        });
        bp.set({
          name: "3",
          type: "g",
          value: magTime
        });
        bp.set({
          name: "4",
          type: "g",
          value: accelTime
        });
        bp.set({
          name: "5",
          type: "g",
          value: biasTime
        });
        await bp.send(this._ch, 174);
      }
      /**
       * Selects the IMU/AHRS algorithm.
       * @returns The sensor algorithm
       * @throws `PhidgetError`
       */
      getAlgorithm() {
        this._assertOpen();
        if (this.data.algorithm === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.algorithm;
      }
      /**
       * Selects the IMU/AHRS algorithm.
       * @throws `PhidgetError`
       * @param algorithm - The sensor algorithm
       */
      async setAlgorithm(algorithm) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: algorithm
        });
        await bp.send(this._ch, 149);
      }
      /**
       * Sets the gain for the magnetometer in the AHRS algorithm. Lower gains reduce sensor noise while slowing response time.
       * @returns The AHRS algorithm magnetometer gain
       * @throws `PhidgetError`
       */
      getAlgorithmMagnetometerGain() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 102:
          case 106:
          case 375:
          case 379:
          case 355:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.algorithmMagnetometerGain === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.algorithmMagnetometerGain;
      }
      /**
       * Sets the gain for the magnetometer in the AHRS algorithm. Lower gains reduce sensor noise while slowing response time.
       * @throws `PhidgetError`
       * @param algorithmMagnetometerGain - The AHRS algorithm magnetometer gain
       */
      async setAlgorithmMagnetometerGain(algorithmMagnetometerGain) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: algorithmMagnetometerGain
        });
        await bp.send(this._ch, 151);
      }
      /**
       * The minimum angular rate the sensor will measure.
       * @returns The angular rate values
       * @throws `PhidgetError`
       */
      getMinAngularRate() {
        var _context3;
        this._assertOpen();
        if (_includesInstanceProperty(_context3 = this.data.minAngularRate).call(_context3, 1e+300)) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minAngularRate;
      }
      /**
       * The maximum angular rate the sensor will measure.
       * @returns The angular rate values
       * @throws `PhidgetError`
       */
      getMaxAngularRate() {
        var _context4;
        this._assertOpen();
        if (_includesInstanceProperty(_context4 = this.data.maxAngularRate).call(_context4, 1e+300)) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxAngularRate;
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `SpatialData` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getDataInterval() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.dataInterval;
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `SpatialData` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * @throws `PhidgetError`
       * @param dataInterval - The data interval value
       */
      async setDataInterval(dataInterval) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: dataInterval
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMinDataInterval() {
        this._assertOpen();
        if (this.data.minDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataInterval;
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMaxDataInterval() {
        this._assertOpen();
        if (this.data.maxDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @returns The data rate for the channel
       * @throws `PhidgetError`
       */
      getDataRate() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return 1000.0 / this.data.dataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       * @param dataRate - The data rate for the channel
       */
      async setDataRate(dataRate) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: Math.round(1000.0 / dataRate)
        });
        bp.set({
          name: "1",
          type: "g",
          value: 1000.0 / dataRate
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMinDataRate() {
        this._assertOpen();
        if (this.data.minDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataRate;
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMaxDataRate() {
        this._assertOpen();
        if (this.data.maxDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataRate;
      }
      /**
       * Set to TRUE to enable the temperature stabilization feature of this device. This enables on-board heating elements to bring the board up to a known temperature to minimize ambient temperature effects on the sensor's reading. You can leave this setting FALSE to conserve power consumption.
       *
       * If you enable heating, it is strongly recommended to keep the board in its enclosure to keep it insulated from moving air.
       *
       * This property is shared by any and all spatial-related objects on this device (Accelerometer, Gyroscope, Magnetometer, Spatial)
       * @returns Whether self-heating temperature stabilization is enabled
       * @throws `PhidgetError`
       */
      getHeatingEnabled() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 355:
          case 360:
          case 365:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.heatingEnabled === 2) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return !!this.data.heatingEnabled;
      }
      /**
       * Set to TRUE to enable the temperature stabilization feature of this device. This enables on-board heating elements to bring the board up to a known temperature to minimize ambient temperature effects on the sensor's reading. You can leave this setting FALSE to conserve power consumption.
       *
       * If you enable heating, it is strongly recommended to keep the board in its enclosure to keep it insulated from moving air.
       *
       * This property is shared by any and all spatial-related objects on this device (Accelerometer, Gyroscope, Magnetometer, Spatial)
       * @throws `PhidgetError`
       * @param heatingEnabled - Whether self-heating temperature stabilization is enabled
       */
      async setHeatingEnabled(heatingEnabled) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: heatingEnabled ? 1 : 0
        });
        await bp.send(this._ch, 170);
      }
      /**
       * The minimum field strength the sensor will measure.
       * @returns The field strength value
       * @throws `PhidgetError`
       */
      getMinMagneticField() {
        var _context5;
        this._assertOpen();
        if (_includesInstanceProperty(_context5 = this.data.minMagneticField).call(_context5, 1e+300)) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minMagneticField;
      }
      /**
       * The maximum field strength the sensor will measure.
       * @returns The field strength value
       * @throws `PhidgetError`
       */
      getMaxMagneticField() {
        var _context6;
        this._assertOpen();
        if (_includesInstanceProperty(_context6 = this.data.maxMagneticField).call(_context6, 1e+300)) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxMagneticField;
      }
      /**
       * Calibrate your device for the environment it will be used in.
       *
       * *   Due to physical location, hard and soft iron offsets, and even bias errors, your device should be calibrated. We have created a calibration program that will provide you with the `MagnetometerCorrectionParameters` for your specific situation. See your device's User Guide for more information.
       * @throws `PhidgetError`
       * @param magneticField - Ambient magnetic field value.
       * @param offset0 - Provided by calibration program.
       * @param offset1 - Provided by calibration program.
       * @param offset2 - Provided by calibration program.
       * @param gain0 - Provided by calibration program.
       * @param gain1 - Provided by calibration program.
       * @param gain2 - Provided by calibration program.
       * @param T0 - Provided by calibration program.
       * @param T1 - Provided by calibration program.
       * @param T2 - Provided by calibration program.
       * @param T3 - Provided by calibration program.
       * @param T4 - Provided by calibration program.
       * @param T5 - Provided by calibration program.
       */
      async setMagnetometerCorrectionParameters(magneticField, offset0, offset1, offset2, gain0, gain1, gain2, T0, T1, T2, T3, T4, T5) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: magneticField
        });
        bp.set({
          name: "1",
          type: "g",
          value: offset0
        });
        bp.set({
          name: "2",
          type: "g",
          value: offset1
        });
        bp.set({
          name: "3",
          type: "g",
          value: offset2
        });
        bp.set({
          name: "4",
          type: "g",
          value: gain0
        });
        bp.set({
          name: "5",
          type: "g",
          value: gain1
        });
        bp.set({
          name: "6",
          type: "g",
          value: gain2
        });
        bp.set({
          name: "7",
          type: "g",
          value: T0
        });
        bp.set({
          name: "8",
          type: "g",
          value: T1
        });
        bp.set({
          name: "9",
          type: "g",
          value: T2
        });
        bp.set({
          name: "10",
          type: "g",
          value: T3
        });
        bp.set({
          name: "11",
          type: "g",
          value: T4
        });
        bp.set({
          name: "12",
          type: "g",
          value: T5
        });
        await bp.send(this._ch, 50);
      }
      /**
       * Selects between high/low precision sensing chips.
       * @returns The sensor precision value
       * @throws `PhidgetError`
       * @internal
       */
      getPrecision() {
        this._assertOpen();
        if (this.data.precision === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.precision;
      }
      /**
       * Selects between high/low precision sensing chips.
       * @throws `PhidgetError`
       * @param precision - The sensor precision value
       * @internal
       */
      async setPrecision(precision) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: precision
        });
        await bp.send(this._ch, 145);
      }
      /**
       * Resets the `MagnetometerCorrectionParameters` to their default values.
       *
       * *   Due to physical location, hard and soft iron offsets, and even bias errors, your device should be calibrated. We have created a calibration program that will provide you with the `MagnetometerCorrectionParameters` for your specific situation. See your device's User Guide for more information.
       * @throws `PhidgetError`
       */
      async resetMagnetometerCorrectionParameters() {
        this._assertOpen();
        const bp = new BridgePacket();
        await bp.send(this._ch, 35);
      }
      /**
       * Saves the `MagnetometerCorrectionParameters`.
       *
       * *   Due to physical location, hard and soft iron offsets, and even bias errors, your device should be calibrated. We have created a calibration program that will provide you with the `MagnetometerCorrectionParameters` for your specific situation. See your device's User Guide for more information.
       * @throws `PhidgetError`
       */
      async saveMagnetometerCorrectionParameters() {
        this._assertOpen();
        const bp = new BridgePacket();
        await bp.send(this._ch, 37);
      }
      /**
       * Zeros the AHRS algorithm.
       * @throws `PhidgetError`
       */
      async zeroAlgorithm() {
        this._assertOpen();
        const bp = new BridgePacket();
        await bp.send(this._ch, 150);
      }
      /**
       * Re-zeros the gyroscope in 1-2 seconds.
       *
       * *   The device must be stationary when zeroing.
       * *   The angular rate will be reported as 0.0°/s while zeroing.
       * *   Zeroing the gyroscope is a method of compensating for the drift that is inherent to all gyroscopes. See your device's User Guide for more information on dealing with drift.
       * @throws `PhidgetError`
       */
      async zeroGyro() {
        this._assertOpen();
        const bp = new BridgePacket();
        await bp.send(this._ch, 106);
      }
    }

    /** @public */
    class Spatial extends SpatialBase {
      /** @internal */
      _transactionLock;
      constructor(ch) {
        super(ch);
        this._transactionLock = new PhidgetLock();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 10:
            {
              if (bp.entryCount > 1) this.data.dataInterval = bp.getNumber(1);else this.data.dataInterval = bp.getNumber(0);
              this._FIREPropertyChange('DataInterval');
              this._FIREPropertyChange('DataRate');
              break;
            }
          case 148:
            {
              const quaternion = bp.getArray(0);
              const timestamp = bp.getNumber(1);
              this.data.quaternion = {
                x: quaternion[0],
                y: quaternion[1],
                z: quaternion[2],
                w: quaternion[3]
              };
              if (this._isAttachedDone && this.onAlgorithmData) {
                try {
                  this.onAlgorithmData(quaternion, timestamp);
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          case 179:
            this.data.heatingEnabled = bp.entries[0].v;
            this._FIREPropertyChange('HeatingEnabled', bp);
            break;
          default:
            super._bridgeInput(bp);
            break;
        }
      }
      /** @internal */
      _hasInitialState() {
        if (this.data.quaternion === null) return false;
        return true;
      }
      getQuaternion() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 93:
          case 98:
          case 148:
          case 152:
          case 371:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.quaternion === null) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.quaternion;
      }
      getEulerAngles() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 93:
          case 98:
          case 148:
          case 152:
          case 371:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.quaternion === null) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        const roll_rad = Math.atan2(2.0 * (this.data.quaternion.x * this.data.quaternion.w + this.data.quaternion.y * this.data.quaternion.z), 1 - 2.0 * (this.data.quaternion.x * this.data.quaternion.x + this.data.quaternion.y * this.data.quaternion.y));
        const pitch_rad = Math.asin(2.0 * (this.data.quaternion.w * this.data.quaternion.y - this.data.quaternion.z * this.data.quaternion.x));
        const heading_rad = Math.atan2(2.0 * (this.data.quaternion.w * this.data.quaternion.z + this.data.quaternion.x * this.data.quaternion.y), 1 - 2.0 * (this.data.quaternion.y * this.data.quaternion.y + this.data.quaternion.z * this.data.quaternion.z));
        const eulerAngles = {
          heading: heading_rad * 180.0 / Math.PI,
          pitch: pitch_rad * 180.0 / Math.PI,
          roll: roll_rad * 180.0 / Math.PI
        };
        return eulerAngles;
      }
    }

    /**
     * The Stepper class powers and controls the stepper motor connected to the Phidget controller, allowing you to change the position, velocity, acceleration, and current limit.
     * @public
     */
    class StepperBase extends PhidgetChannel {
      /** @internal */
      data;
      onPositionChange = null;
      /** @internal */
      _gotPositionChangeErrorEvent;
      onVelocityChange = null;
      /** @internal */
      _gotVelocityChangeErrorEvent;
      onStopped = null;
      /** @internal */
      _gotStoppedErrorEvent;
      constructor(ch) {
        super(ch);
        this._class = exports.ChannelClass.STEPPER;
        this.name = "Stepper";
        this.data = this._initData();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 40:
            this.data.acceleration = bp.entries[0].v;
            this._FIREPropertyChange('Acceleration', bp);
            break;
          case 49:
            this.data.controlMode = bp.entries[0].v;
            this._FIREPropertyChange('ControlMode', bp);
            break;
          case 51:
            this.data.currentLimit = bp.entries[0].v;
            this._FIREPropertyChange('CurrentLimit', bp);
            break;
          case 54:
            if (bp.entryCount > 1) this.data.dataInterval = bp.entries[1].v;else this.data.dataInterval = bp.entries[0].v;
            this._FIREPropertyChange('DataInterval', bp);
            this._FIREPropertyChange('DataRate', bp);
            break;
          case 57:
            this.data.engaged = bp.entries[0].v;
            this._FIREPropertyChange('Engaged', bp);
            break;
          case 146:
            break;
          case 63:
            this.data.holdingCurrentLimit = bp.entries[0].v;
            this._FIREPropertyChange('HoldingCurrentLimit', bp);
            break;
          case 147:
            break;
          case 83:
            this.data.targetPosition = bp.entries[0].v;
            this._FIREPropertyChange('TargetPosition', bp);
            break;
          case 85:
            this.data.velocityLimit = bp.entries[0].v;
            this._FIREPropertyChange('VelocityLimit', bp);
            break;
          case 91:
            {
              if (this._isAttachedDone && this.onStopped) {
                try {
                  this.onStopped();
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          default:
            throw new PhidgetError(exports.ErrorCode.INVALID_PACKET, "Unsupported bridge packet: 0x" + bp.vpkt.toString(16));
        }
      }
      /** @internal */
      _initData() {
        return {
          positionOffset: 0,
          dataInterval: 1e+300,
          minDataRate: 1e+300,
          maxDataRate: 1e+300,
          holdingCurrentLimit: 1e+300,
          minDataInterval: 4294967295,
          maxDataInterval: 4294967295,
          maxPosition: 9223372036854776000,
          maxVelocityLimit: 1e+300,
          maxAcceleration: 1e+300,
          maxCurrentLimit: 1e+300,
          minPosition: 9223372036854776000,
          minVelocityLimit: 1e+300,
          minAcceleration: 1e+300,
          minCurrentLimit: 1e+300,
          controlMode: 2147483647,
          position: 9223372036854776000,
          targetPosition: 9223372036854776000,
          velocityLimit: 1e+300,
          velocity: 1e+300,
          acceleration: 1e+300,
          currentLimit: 1e+300,
          isMoving: 2,
          engaged: 2,
          rescaleFactor: 1e+300,
          maxFailsafeTime: 4294967295,
          minFailsafeTime: 4294967295
        };
      }
      /** @internal */
      _initAfterOpen() {}
      /** @internal */
      async _setDefaults() {}
      /** @internal */
      _hasInitialState() {
        return true;
      }
      /** @internal */
      _fireInitialEvents() {}
      /**
       * The rate at which the controller can change the motor's `velocity`.
       *
       * *   Use the `rescaleFactor` to convert the units of this property into more intuitive units such as rotations or degrees.
       *
       *
       * For more information about `acceleration`, visit our [Stepper API Guide](https://www.phidgets.com/docs/Stepper_API_Guide#Acceleration).
       * @throws `PhidgetError`
       */
      get acceleration() {
        return this.getAcceleration();
      }
      /**
       * The minimum value that `acceleration` can be set to.
       * @throws `PhidgetError`
       */
      get minAcceleration() {
        return this.getMinAcceleration();
      }
      /**
       * The maximum value that `acceleration` can be set to.
       * @throws `PhidgetError`
       */
      get maxAcceleration() {
        return this.getMaxAcceleration();
      }
      /**
       * This setting changes how the controller moves your motor.
       *
       * *   In `phidget22.StepperControlMode.STEP`, a `targetPosition` is specified and the controller moves the motor toward the target.
       * *   In `phidget22.StepperControlMode.RUN`, the controller continuously rotates the motor in a direction that is specified by the a `velocityLimit`.
       *
       *
       * For more information about `controlMode`, visit our [Stepper API Guide](https://www.phidgets.com/docs/Stepper_API_Guide#Control_Mode).
       * @throws `PhidgetError`
       */
      get controlMode() {
        return this.getControlMode();
      }
      /**
       * The current through the motor will be limited by the `currentLimit`.
       *
       *
       * For more information about `currentLimit`, visit our [Stepper API Guide](https://www.phidgets.com/docs/Stepper_API_Guide#Current_Limit).
       * @throws `PhidgetError`
       */
      get currentLimit() {
        return this.getCurrentLimit();
      }
      /**
       * The minimum value that `currentLimit` and `holdingCurrentLimit` can be set to.
       * @throws `PhidgetError`
       */
      get minCurrentLimit() {
        return this.getMinCurrentLimit();
      }
      /**
       * The maximum value that `currentLimit` and `holdingCurrentLimit` can be set to.
       * @throws `PhidgetError`
       */
      get maxCurrentLimit() {
        return this.getMaxCurrentLimit();
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `PositionChange` / `VelocityChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * @throws `PhidgetError`
       */
      get dataInterval() {
        return this.getDataInterval();
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get minDataInterval() {
        return this.getMinDataInterval();
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataInterval() {
        return this.getMaxDataInterval();
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       */
      get dataRate() {
        return this.getDataRate();
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get minDataRate() {
        return this.getMinDataRate();
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataRate() {
        return this.getMaxDataRate();
      }
      /**
       * The controller must be engaged in order to move the motor.
       *
       * *   In `phidget22.StepperControlMode.STEP`, a `targetPosition` must be defined or the controller will remain disengaged.
       *
       * *   In `phidget22.StepperControlMode.RUN`, the controller will activate immediately after engage has been set to TRUE.
       *
       *
       * For more information about `engaged`, visit our [Stepper API Guide](https://www.phidgets.com/docs/Stepper_API_Guide#Engage/Disengage).
       * @throws `PhidgetError`
       */
      get engaged() {
        return this.getEngaged();
      }
      /**
       * The minimum value that `failsafeTime` can be set to when calling `enableFailsafe()`.
       * @throws `PhidgetError`
       */
      get minFailsafeTime() {
        return this.getMinFailsafeTime();
      }
      /**
       * The maximum value that `failsafeTime` can be set to when calling `enableFailsafe()`.
       * @throws `PhidgetError`
       */
      get maxFailsafeTime() {
        return this.getMaxFailsafeTime();
      }
      /**
       * The current through the motor will be limited by the `holdingCurrentLimit` while `isMoving` is FALSE and `engaged` is TRUE. If no `holdingCurrentLimit` is specified, the current through the motor will be limited by the `currentLimit` instead.
       *
       *
       * For more information about `holdingCurrentLimit`, visit our [Stepper API Guide](https://www.phidgets.com/docs/Stepper_API_Guide#Holding_Current_Limit).
       * @throws `PhidgetError`
       */
      get holdingCurrentLimit() {
        return this.getHoldingCurrentLimit();
      }
      /**
       * `isMoving` returns TRUE while the controller is moving the motor.
       *
       * *   The controller receives no feedback from the motor, so this may not always reflect reality.
       *
       *
       * For more information about `isMoving`, visit our [Stepper API Guide](https://www.phidgets.com/docs/Stepper_API_Guide#isMoving).
       * @throws `PhidgetError`
       */
      get isMoving() {
        return this.getIsMoving();
      }
      /**
       * The most recent Position value reported by the controller.
       *
       * *   Use the `rescaleFactor` to convert the units of this property into more intuitive units such as rotations or degrees.
       *
       *
       * For more information about `position`, visit our [Stepper API Guide](https://www.phidgets.com/docs/Stepper_API_Guide#Motor_Position).
       * @throws `PhidgetError`
       */
      get position() {
        return this.getPosition();
      }
      /**
       * The minimum value that `targetPosition` can be set to.
       * @throws `PhidgetError`
       */
      get minPosition() {
        return this.getMinPosition();
      }
      /**
       * The maximum value that `targetPosition` can be set to.
       * @throws `PhidgetError`
       */
      get maxPosition() {
        return this.getMaxPosition();
      }
      /**
       * Change the units of your parameters so that your application is more intuitive
       *
       * *   View the Specifications tab of your stepper controller to see the default units. Most controllers have default units of 1/16 steps per count.
       *
       *
       * For more information about `rescaleFactor`, visit our [Stepper API Guide](https://www.phidgets.com/docs/Stepper_API_Guide#Rescale_Factor).
       * @throws `PhidgetError`
       */
      get rescaleFactor() {
        return this.getRescaleFactor();
      }
      set rescaleFactor(rescaleFactor) {
        this.setRescaleFactor(rescaleFactor);
      }
      /**
       * The controller will move the motor toward the `targetPosition` when `engaged` is TRUE.
       *
       * *   `targetPosition` is only used when `phidget22.StepperControlMode.STEP` is selected.
       * *   Use the `rescaleFactor` to convert the units of this property into more intuitive units such as rotations or degrees.
       *
       *
       * For more information about `targetPosition`, visit our [Stepper API Guide](https://www.phidgets.com/docs/Stepper_API_Guide#Target_Position).
       * @throws `PhidgetError`
       */
      get targetPosition() {
        return this.getTargetPosition();
      }
      /**
       * The most recent velocity value that the controller has reported.
       *
       * *   Use the `rescaleFactor` to convert the units of this property into more intuitive units such as rotations or degrees.
       *
       *
       * For more information about `velocity`, visit our [Stepper API Guide](https://www.phidgets.com/docs/Stepper_API_Guide#Motor_Velocity).
       * @throws `PhidgetError`
       */
      get velocity() {
        return this.getVelocity();
      }
      /**
       * The controller will limit the motor's velocity to this value.
       *
       * *   When `phidget22.StepperControlMode.STEP` is selected, the `minVelocityLimit` has a value of 0. This is because the sign (±) of the `targetPosition` will indicate the direction.
       * *   When in `phidget22.StepperControlMode.RUN`, the `minVelocityLimit` has a value of -1 \* `maxVelocityLimit`. This is because there is no `targetPosition`, so the direction is defined by the sign (±) of the `velocityLimit`.
       * *   While `velocityLimit` is listed as a double, it is rounded down to an integer number of 1/16th steps when sent to the board since the board is limited by a minimum unit of 1/16th steps/s. This is especially important to consider when using different `rescaleFactor` values where converting to units of, for example, RPM results in 1.5RPM (80 1/16th steps/s) and 1.509375 RPM (80.5 1/16th steps/s) both being sent to the board as 80 1/16th steps/s.
       * *   Use the `rescaleFactor` to convert the units of this property into more intuitive units such as rotations or degrees.
       * @throws `PhidgetError`
       */
      get velocityLimit() {
        return this.getVelocityLimit();
      }
      /**
       * The minimum value that `velocityLimit` can be set to.
       * @throws `PhidgetError`
       */
      get minVelocityLimit() {
        return this.getMinVelocityLimit();
      }
      /**
       * The maximum value that `velocityLimit` can be set to.
       * @throws `PhidgetError`
       */
      get maxVelocityLimit() {
        return this.getMaxVelocityLimit();
      }
      /**
       * This setting changes how the controller moves your motor.
       *
       * *   In `phidget22.StepperControlMode.STEP`, a `targetPosition` is specified and the controller moves the motor toward the target.
       * *   In `phidget22.StepperControlMode.RUN`, the controller continuously rotates the motor in a direction that is specified by the a `velocityLimit`.
       *
       *
       * For more information about `controlMode`, visit our [Stepper API Guide](https://www.phidgets.com/docs/Stepper_API_Guide#Control_Mode).
       * @returns The control mode value
       * @throws `PhidgetError`
       */
      getControlMode() {
        this._assertOpen();
        if (this.data.controlMode === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.controlMode;
      }
      /**
       * This setting changes how the controller moves your motor.
       *
       * *   In `phidget22.StepperControlMode.STEP`, a `targetPosition` is specified and the controller moves the motor toward the target.
       * *   In `phidget22.StepperControlMode.RUN`, the controller continuously rotates the motor in a direction that is specified by the a `velocityLimit`.
       *
       *
       * For more information about `controlMode`, visit our [Stepper API Guide](https://www.phidgets.com/docs/Stepper_API_Guide#Control_Mode).
       * @throws `PhidgetError`
       * @param controlMode - The control mode value
       */
      async setControlMode(controlMode) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: controlMode
        });
        await bp.send(this._ch, 49);
      }
      /**
       * The current through the motor will be limited by the `currentLimit`.
       *
       *
       * For more information about `currentLimit`, visit our [Stepper API Guide](https://www.phidgets.com/docs/Stepper_API_Guide#Current_Limit).
       * @returns The current limit value
       * @throws `PhidgetError`
       */
      getCurrentLimit() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 166:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.currentLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.currentLimit;
      }
      /**
       * The current through the motor will be limited by the `currentLimit`.
       *
       *
       * For more information about `currentLimit`, visit our [Stepper API Guide](https://www.phidgets.com/docs/Stepper_API_Guide#Current_Limit).
       * @throws `PhidgetError`
       * @param currentLimit - The current limit value
       */
      async setCurrentLimit(currentLimit) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: currentLimit
        });
        await bp.send(this._ch, 51);
      }
      /**
       * The minimum value that `currentLimit` and `holdingCurrentLimit` can be set to.
       * @returns The current limit
       * @throws `PhidgetError`
       */
      getMinCurrentLimit() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 166:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.minCurrentLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minCurrentLimit;
      }
      /**
       * The maximum value that `currentLimit` and `holdingCurrentLimit` can be set to.
       * @returns The current limit
       * @throws `PhidgetError`
       */
      getMaxCurrentLimit() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 166:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.maxCurrentLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxCurrentLimit;
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `PositionChange` / `VelocityChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getDataInterval() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.dataInterval;
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `PositionChange` / `VelocityChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * @throws `PhidgetError`
       * @param dataInterval - The data interval value
       */
      async setDataInterval(dataInterval) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: dataInterval
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMinDataInterval() {
        this._assertOpen();
        if (this.data.minDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataInterval;
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMaxDataInterval() {
        this._assertOpen();
        if (this.data.maxDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @returns The data rate for the channel
       * @throws `PhidgetError`
       */
      getDataRate() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return 1000.0 / this.data.dataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       * @param dataRate - The data rate for the channel
       */
      async setDataRate(dataRate) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: Math.round(1000.0 / dataRate)
        });
        bp.set({
          name: "1",
          type: "g",
          value: 1000.0 / dataRate
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMinDataRate() {
        this._assertOpen();
        if (this.data.minDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataRate;
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMaxDataRate() {
        this._assertOpen();
        if (this.data.maxDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataRate;
      }
      /**
       * The controller must be engaged in order to move the motor.
       *
       * *   In `phidget22.StepperControlMode.STEP`, a `targetPosition` must be defined or the controller will remain disengaged.
       *
       * *   In `phidget22.StepperControlMode.RUN`, the controller will activate immediately after engage has been set to TRUE.
       *
       *
       * For more information about `engaged`, visit our [Stepper API Guide](https://www.phidgets.com/docs/Stepper_API_Guide#Engage/Disengage).
       * @returns The engaged state
       * @throws `PhidgetError`
       */
      getEngaged() {
        this._assertOpen();
        if (this.data.engaged === 2) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return !!this.data.engaged;
      }
      /**
       * The controller must be engaged in order to move the motor.
       *
       * *   In `phidget22.StepperControlMode.STEP`, a `targetPosition` must be defined or the controller will remain disengaged.
       *
       * *   In `phidget22.StepperControlMode.RUN`, the controller will activate immediately after engage has been set to TRUE.
       *
       *
       * For more information about `engaged`, visit our [Stepper API Guide](https://www.phidgets.com/docs/Stepper_API_Guide#Engage/Disengage).
       * @throws `PhidgetError`
       * @param engaged - The engaged state
       */
      async setEngaged(engaged) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: engaged ? 1 : 0
        });
        await bp.send(this._ch, 57);
      }
      /**
       * Enables the **failsafe** feature for the channel, with the specified **failsafe time**.
       *
       * Enabling the failsafe feature starts a recurring **failsafe timer** for the channel. Once the failsafe is enabled, the timer must be reset within the specified time or the channel will enter a **failsafe state**. For Stepper Motor channels, this will disengage the motor. The failsafe timer can be reset by using any of the following API calls:
       *
       * *   `setAcceleration()`
       * *   `setControlMode()`
       * *   `setCurrentLimit()`
       * *   `setDataInterval()`
       * *   `setDataRate()`
       * *   `setEngaged()`
       * *   `setHoldingCurrentLimit()`
       * *   `setVelocityLimit()`
       * *   `resetFailsafe()`
       *
       * For more information about failsafe, visit our [Failsafe Guide](https://www.phidgets.com/docs/Failsafe_Guide).
       * @throws `PhidgetError`
       * @param failsafeTime - Failsafe timeout in milliseconds
       */
      async enableFailsafe(failsafeTime) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: failsafeTime
        });
        await bp.send(this._ch, 146);
      }
      /**
       * The minimum value that `failsafeTime` can be set to when calling `enableFailsafe()`.
       * @returns The failsafe time
       * @throws `PhidgetError`
       */
      getMinFailsafeTime() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 166:
          case 167:
          case 181:
          case 428:
          case 430:
          case 432:
          case 434:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.minFailsafeTime === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minFailsafeTime;
      }
      /**
       * The maximum value that `failsafeTime` can be set to when calling `enableFailsafe()`.
       * @returns The failsafe time
       * @throws `PhidgetError`
       */
      getMaxFailsafeTime() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 166:
          case 167:
          case 181:
          case 428:
          case 430:
          case 432:
          case 434:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.maxFailsafeTime === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxFailsafeTime;
      }
      /**
       * The current through the motor will be limited by the `holdingCurrentLimit` while `isMoving` is FALSE and `engaged` is TRUE. If no `holdingCurrentLimit` is specified, the current through the motor will be limited by the `currentLimit` instead.
       *
       *
       * For more information about `holdingCurrentLimit`, visit our [Stepper API Guide](https://www.phidgets.com/docs/Stepper_API_Guide#Holding_Current_Limit).
       * @returns The current value
       * @throws `PhidgetError`
       */
      getHoldingCurrentLimit() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 166:
          case 167:
          case 181:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.holdingCurrentLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.holdingCurrentLimit;
      }
      /**
       * The current through the motor will be limited by the `holdingCurrentLimit` while `isMoving` is FALSE and `engaged` is TRUE. If no `holdingCurrentLimit` is specified, the current through the motor will be limited by the `currentLimit` instead.
       *
       *
       * For more information about `holdingCurrentLimit`, visit our [Stepper API Guide](https://www.phidgets.com/docs/Stepper_API_Guide#Holding_Current_Limit).
       * @throws `PhidgetError`
       * @param holdingCurrentLimit - The current value
       */
      async setHoldingCurrentLimit(holdingCurrentLimit) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: holdingCurrentLimit
        });
        await bp.send(this._ch, 63);
      }
      /**
       * `isMoving` returns TRUE while the controller is moving the motor.
       *
       * *   The controller receives no feedback from the motor, so this may not always reflect reality.
       *
       *
       * For more information about `isMoving`, visit our [Stepper API Guide](https://www.phidgets.com/docs/Stepper_API_Guide#isMoving).
       * @returns The moving state
       * @throws `PhidgetError`
       */
      getIsMoving() {
        this._assertOpen();
        if (this.data.isMoving === 2) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return !!this.data.isMoving;
      }
      /**
       * Change the units of your parameters so that your application is more intuitive
       *
       * *   View the Specifications tab of your stepper controller to see the default units. Most controllers have default units of 1/16 steps per count.
       *
       *
       * For more information about `rescaleFactor`, visit our [Stepper API Guide](https://www.phidgets.com/docs/Stepper_API_Guide#Rescale_Factor).
       * @returns The rescale factor value
       * @throws `PhidgetError`
       */
      getRescaleFactor() {
        this._assertOpen();
        if (this.data.rescaleFactor === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.rescaleFactor;
      }
      /**
       * Resets the failsafe timer, if one has been set. See `enableFailsafe()` for details.
       *
       * This function will fail if no failsafe timer has been set for the channel.
       * @throws `PhidgetError`
       */
      async resetFailsafe() {
        this._assertOpen();
        const bp = new BridgePacket();
        await bp.send(this._ch, 147);
      }
    }

    /** @public */
    class Stepper extends StepperBase {
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 29:
            this.data.position = bp.getNumber(0);
            if (this._isAttachedDone && this.onPositionChange) {
              try {
                this.onPositionChange((this.data.position + this.data.positionOffset) * this.data.rescaleFactor);
              } catch (err) {
                logEventException(err);
              }
            }
            break;
          case 100:
            this.data.velocity = bp.getNumber(0);
            if (this.data.velocity !== 0) this.data.isMoving = 1;
            if (this._isAttachedDone && this.onVelocityChange) {
              try {
                this.onVelocityChange(this.data.velocity * this.data.rescaleFactor);
              } catch (err) {
                logEventException(err);
              }
            }
            break;
          case 49:
            super._bridgeInput(bp);
            switch (this.data.controlMode) {
              case exports.StepperControlMode.STEP:
                this.data.minVelocityLimit = 0;
                break;
              case exports.StepperControlMode.RUN:
                this.data.minVelocityLimit = -this.data.maxVelocityLimit;
                break;
            }
            break;
          case 91:
            this.data.isMoving = 0;
            super._bridgeInput(bp);
            break;
          case 57:
            super._bridgeInput(bp);
            if (this.data.engaged && this.data.velocityLimit !== 0 && (this.data.position !== this.data.targetPosition || this.data.controlMode === exports.StepperControlMode.RUN)) this.data.isMoving = 1;
            break;
          case 85:
            super._bridgeInput(bp);
            if (this.data.engaged && this.data.velocityLimit !== 0 && this.data.position !== this.data.targetPosition) this.data.isMoving = 1;
            if (this.data.controlMode === exports.StepperControlMode.RUN) {
              if (this.data.velocityLimit > 0) this.data.targetPosition = this.data.maxPosition;else if (this.data.velocityLimit < 0) this.data.targetPosition = this.data.minPosition;
            }
            break;
          case 83:
            super._bridgeInput(bp);
            if (this.data.engaged && this.data.velocityLimit !== 0 && (this.data.position !== this.data.targetPosition || this.data.controlMode === exports.StepperControlMode.RUN)) this.data.isMoving = 1;
            break;
          default:
            super._bridgeInput(bp);
            break;
        }
      }
      /** @internal */
      _initAfterOpen() {
        super._initAfterOpen();
        if (this.data.position == 9223372036854776000) this.data.position = 0;
        if (this.data.velocity == 1e+300) this.data.velocity = 0;
        if (this.data.isMoving == 2) this.data.isMoving = 0;
      }
      getAcceleration() {
        this._assertOpen();
        if (this.data.acceleration === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.acceleration * this.data.rescaleFactor;
      }
      async setAcceleration(acceleration) {
        this._assertOpen();
        const calcAccel = acceleration / this.data.rescaleFactor;
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: calcAccel
        });
        await bp.send(this._ch, 40);
      }
      getMinAcceleration() {
        this._assertOpen();
        if (this.data.minAcceleration === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minAcceleration * this.data.rescaleFactor;
      }
      getMaxAcceleration() {
        this._assertOpen();
        if (this.data.maxAcceleration === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxAcceleration * this.data.rescaleFactor;
      }
      getPosition() {
        this._assertOpen();
        if (this.data.position === 9223372036854776000) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return (this.data.position + this.data.positionOffset) * this.data.rescaleFactor;
      }
      getMinPosition() {
        this._assertOpen();
        if (this.data.minPosition === 9223372036854776000) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return (this.data.minPosition + this.data.positionOffset) * this.data.rescaleFactor;
      }
      getMaxPosition() {
        this._assertOpen();
        if (this.data.maxPosition === 9223372036854776000) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return (this.data.maxPosition + this.data.positionOffset) * this.data.rescaleFactor;
      }
      setRescaleFactor(rescaleFactor) {
        this._assertOpen();
        this.data.rescaleFactor = rescaleFactor;
      }
      getTargetPosition() {
        this._assertOpen();
        if (this.data.targetPosition === 9223372036854776000) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return (this.data.targetPosition + this.data.positionOffset) * this.data.rescaleFactor;
      }
      async setTargetPosition(targetPosition) {
        this._assertOpen();
        const calcPosition = targetPosition / this.data.rescaleFactor - this.data.positionOffset;
        if (calcPosition < this.data.minPosition || calcPosition > this.data.maxPosition) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Value must be in range: " + this.minPosition + " - " + this.maxPosition + ".");
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "l",
          value: calcPosition
        });
        await bp.send(this._ch, 83);
      }
      getVelocity() {
        this._assertOpen();
        if (this.data.velocity === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.velocity * this.data.rescaleFactor;
      }
      getVelocityLimit() {
        this._assertOpen();
        if (this.data.velocityLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.velocityLimit * this.data.rescaleFactor;
      }
      async setVelocityLimit(velocityLimit) {
        this._assertOpen();
        const calcLimit = velocityLimit / this.data.rescaleFactor;
        if (calcLimit < this.data.minVelocityLimit || calcLimit > this.data.maxVelocityLimit) throw new PhidgetError(exports.ErrorCode.INVALID_ARGUMENT, "Value must be in range: " + this.minVelocityLimit + " - " + this.maxVelocityLimit + ".");
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: calcLimit
        });
        await bp.send(this._ch, 85);
      }
      getMaxVelocityLimit() {
        this._assertOpen();
        if (this.data.maxVelocityLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxVelocityLimit * this.data.rescaleFactor;
      }
      getMinVelocityLimit() {
        this._assertOpen();
        if (this.data.minVelocityLimit === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minVelocityLimit * this.data.rescaleFactor;
      }
      addPositionOffset(positionOffset) {
        this._assertOpen();
        this.data.positionOffset += positionOffset / this.data.rescaleFactor;
      }
    }

    /**
     * The Temperature Sensor class gathers data from the temperature sensor on a Phidget board. This includes on-board ambient temperature sensors, connected thermocouples or platinum RTDs, and IR temperature sensors. This class is also used to measure the temperature on some high-power Phidget boards such as motor controllers for safety reasons.
     *
     * If you're using a simple 0-5V sensor that does not have its own firmware, use the VoltageInput or VoltageRatioInput class instead, as specified for your device.
     * @public
     */
    class TemperatureSensorBase extends PhidgetChannel {
      /** @internal */
      data;
      onTemperatureChange = null;
      /** @internal */
      _gotTemperatureChangeErrorEvent;
      constructor(ch) {
        super(ch);
        this._class = exports.ChannelClass.TEMPERATURE_SENSOR;
        this.name = "TemperatureSensor";
        this.data = this._initData();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 54:
            if (bp.entryCount > 1) this.data.dataInterval = bp.entries[1].v;else this.data.dataInterval = bp.entries[0].v;
            this._FIREPropertyChange('DataInterval', bp);
            this._FIREPropertyChange('DataRate', bp);
            break;
          case 76:
            this.data.RTDType = bp.entries[0].v;
            this._FIREPropertyChange('RTDType', bp);
            break;
          case 77:
            this.data.RTDWireSetup = bp.entries[0].v;
            this._FIREPropertyChange('RTDWireSetup', bp);
            break;
          case 46:
            this.data.temperatureChangeTrigger = bp.entries[0].v;
            this._FIREPropertyChange('TemperatureChangeTrigger', bp);
            break;
          case 84:
            this.data.thermocoupleType = bp.entries[0].v;
            this._FIREPropertyChange('ThermocoupleType', bp);
            break;
          case 95:
            {
              this.data.temperature = bp.entries[0].v;
              if (this._isAttachedDone && this.onTemperatureChange) {
                try {
                  this.onTemperatureChange(this.data.temperature);
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          default:
            throw new PhidgetError(exports.ErrorCode.INVALID_PACKET, "Unsupported bridge packet: 0x" + bp.vpkt.toString(16));
        }
      }
      /** @internal */
      _initData() {
        return {
          dataInterval: 1e+300,
          maxDataInterval: 4294967295,
          minDataRate: 1e+300,
          maxDataRate: 1e+300,
          maxTemperature: 1e+300,
          maxTemperatureChangeTrigger: 1e+300,
          minDataInterval: 4294967295,
          minTemperature: 1e+300,
          minTemperatureChangeTrigger: 1e+300,
          temperature: 1e+300,
          temperatureChangeTrigger: 1e+300,
          RTDType: 2147483647,
          RTDWireSetup: 2147483647,
          thermocoupleType: 2147483647
        };
      }
      /** @internal */
      _initAfterOpen() {}
      /** @internal */
      async _setDefaults() {}
      /** @internal */
      _hasInitialState() {
        return true;
      }
      /** @internal */
      _fireInitialEvents() {}
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `TemperatureChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between `TemperatureChange` events can also be affected by the `temperatureChangeTrigger`.
       * @throws `PhidgetError`
       */
      get dataInterval() {
        return this.getDataInterval();
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get minDataInterval() {
        return this.getMinDataInterval();
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataInterval() {
        return this.getMaxDataInterval();
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       */
      get dataRate() {
        return this.getDataRate();
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get minDataRate() {
        return this.getMinDataRate();
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataRate() {
        return this.getMaxDataRate();
      }
      /**
       * The `RTDType` must correspond to the RTD type you are using in your application.
       *
       * *   If you are unsure which `RTDType` to use, visit your device's User Guide for more information.
       * @throws `PhidgetError`
       */
      get RTDType() {
        return this.getRTDType();
      }
      /**
       * The `RTDWireSetup` must correspond to the wire configuration you are using in your application.
       *
       * *   If you are unsure which `RTDWireSetup` to use, visit your device's User Guide for more information.
       * @throws `PhidgetError`
       */
      get RTDWireSetup() {
        return this.getRTDWireSetup();
      }
      /**
       * The most recent temperature value that the channel has reported.
       *
       * *   This value will always be between `minTemperature` and `maxTemperature`.
       * @throws `PhidgetError`
       */
      get temperature() {
        return this.getTemperature();
      }
      /**
       * The minimum value the `TemperatureChange` event will report.
       * @throws `PhidgetError`
       */
      get minTemperature() {
        return this.getMinTemperature();
      }
      /**
       * The maximum value the `TemperatureChange` event will report.
       * @throws `PhidgetError`
       */
      get maxTemperature() {
        return this.getMaxTemperature();
      }
      /**
       * The channel will not issue a `TemperatureChange` event until the temperature value has changed by the amount specified by the `temperatureChangeTrigger`.
       *
       * *   Setting the `temperatureChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @throws `PhidgetError`
       */
      get temperatureChangeTrigger() {
        return this.getTemperatureChangeTrigger();
      }
      /**
       * The minimum value that `temperatureChangeTrigger` can be set to.
       * @throws `PhidgetError`
       */
      get minTemperatureChangeTrigger() {
        return this.getMinTemperatureChangeTrigger();
      }
      /**
       * The maximum value that `temperatureChangeTrigger` can be set to.
       * @throws `PhidgetError`
       */
      get maxTemperatureChangeTrigger() {
        return this.getMaxTemperatureChangeTrigger();
      }
      /**
       * The `thermocoupleType` must correspond to the thermocouple type you are using in your application.
       *
       * *   If you are unsure which `thermocoupleType` to use, visit the [Thermocouple Primer](https://www.phidgets.com/docs/Thermocouple_Primer) for more information.
       * @throws `PhidgetError`
       */
      get thermocoupleType() {
        return this.getThermocoupleType();
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `TemperatureChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between `TemperatureChange` events can also be affected by the `temperatureChangeTrigger`.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getDataInterval() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.dataInterval;
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another `TemperatureChange` event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between `TemperatureChange` events can also be affected by the `temperatureChangeTrigger`.
       * @throws `PhidgetError`
       * @param dataInterval - The data interval value
       */
      async setDataInterval(dataInterval) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: dataInterval
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMinDataInterval() {
        this._assertOpen();
        if (this.data.minDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataInterval;
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMaxDataInterval() {
        this._assertOpen();
        if (this.data.maxDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @returns The data rate for the channel
       * @throws `PhidgetError`
       */
      getDataRate() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return 1000.0 / this.data.dataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       * @param dataRate - The data rate for the channel
       */
      async setDataRate(dataRate) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: Math.round(1000.0 / dataRate)
        });
        bp.set({
          name: "1",
          type: "g",
          value: 1000.0 / dataRate
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMinDataRate() {
        this._assertOpen();
        if (this.data.minDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataRate;
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMaxDataRate() {
        this._assertOpen();
        if (this.data.maxDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataRate;
      }
      /**
       * The `RTDType` must correspond to the RTD type you are using in your application.
       *
       * *   If you are unsure which `RTDType` to use, visit your device's User Guide for more information.
       * @returns The RTD type
       * @throws `PhidgetError`
       */
      getRTDType() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 452:
          case 454:
          case 456:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.RTDType === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.RTDType;
      }
      /**
       * The `RTDType` must correspond to the RTD type you are using in your application.
       *
       * *   If you are unsure which `RTDType` to use, visit your device's User Guide for more information.
       * @throws `PhidgetError`
       * @param RTDType - The RTD type
       */
      async setRTDType(RTDType) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: RTDType
        });
        await bp.send(this._ch, 76);
      }
      /**
       * The `RTDWireSetup` must correspond to the wire configuration you are using in your application.
       *
       * *   If you are unsure which `RTDWireSetup` to use, visit your device's User Guide for more information.
       * @returns The RTD wire setup
       * @throws `PhidgetError`
       */
      getRTDWireSetup() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 452:
          case 454:
          case 456:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.RTDWireSetup === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.RTDWireSetup;
      }
      /**
       * The `RTDWireSetup` must correspond to the wire configuration you are using in your application.
       *
       * *   If you are unsure which `RTDWireSetup` to use, visit your device's User Guide for more information.
       * @throws `PhidgetError`
       * @param RTDWireSetup - The RTD wire setup
       */
      async setRTDWireSetup(RTDWireSetup) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: RTDWireSetup
        });
        await bp.send(this._ch, 77);
      }
      /**
       * The most recent temperature value that the channel has reported.
       *
       * *   This value will always be between `minTemperature` and `maxTemperature`.
       * @returns The temperature value
       * @throws `PhidgetError`
       */
      getTemperature() {
        this._assertOpen();
        if (this.data.temperature === 1e+300 || Number.isNaN(this.data.temperature)) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        if (this.data.temperature > this.data.maxTemperature) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE_HIGH);
        if (this.data.temperature < this.data.minTemperature) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE_LOW);
        return this.data.temperature;
      }
      /**
       * The minimum value the `TemperatureChange` event will report.
       * @returns The temperature value
       * @throws `PhidgetError`
       */
      getMinTemperature() {
        this._assertOpen();
        if (this.data.minTemperature === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minTemperature;
      }
      /**
       * The maximum value the `TemperatureChange` event will report.
       * @returns The temperature value
       * @throws `PhidgetError`
       */
      getMaxTemperature() {
        this._assertOpen();
        if (this.data.maxTemperature === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxTemperature;
      }
      /**
       * The channel will not issue a `TemperatureChange` event until the temperature value has changed by the amount specified by the `temperatureChangeTrigger`.
       *
       * *   Setting the `temperatureChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getTemperatureChangeTrigger() {
        this._assertOpen();
        if (this.data.temperatureChangeTrigger === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.temperatureChangeTrigger;
      }
      /**
       * The channel will not issue a `TemperatureChange` event until the temperature value has changed by the amount specified by the `temperatureChangeTrigger`.
       *
       * *   Setting the `temperatureChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @throws `PhidgetError`
       * @param temperatureChangeTrigger - The change trigger value
       */
      async setTemperatureChangeTrigger(temperatureChangeTrigger) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: temperatureChangeTrigger
        });
        await bp.send(this._ch, 46);
      }
      /**
       * The minimum value that `temperatureChangeTrigger` can be set to.
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getMinTemperatureChangeTrigger() {
        this._assertOpen();
        if (this.data.minTemperatureChangeTrigger === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minTemperatureChangeTrigger;
      }
      /**
       * The maximum value that `temperatureChangeTrigger` can be set to.
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getMaxTemperatureChangeTrigger() {
        this._assertOpen();
        if (this.data.maxTemperatureChangeTrigger === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxTemperatureChangeTrigger;
      }
      /**
       * The `thermocoupleType` must correspond to the thermocouple type you are using in your application.
       *
       * *   If you are unsure which `thermocoupleType` to use, visit the [Thermocouple Primer](https://www.phidgets.com/docs/Thermocouple_Primer) for more information.
       * @returns The thermocouple type
       * @throws `PhidgetError`
       */
      getThermocoupleType() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 118:
          case 121:
          case 125:
          case 127:
          case 130:
          case 133:
          case 443:
          case 446:
          case 449:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.thermocoupleType === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.thermocoupleType;
      }
      /**
       * The `thermocoupleType` must correspond to the thermocouple type you are using in your application.
       *
       * *   If you are unsure which `thermocoupleType` to use, visit the [Thermocouple Primer](https://www.phidgets.com/docs/Thermocouple_Primer) for more information.
       * @throws `PhidgetError`
       * @param thermocoupleType - The thermocouple type
       */
      async setThermocoupleType(thermocoupleType) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: thermocoupleType
        });
        await bp.send(this._ch, 84);
      }
    }

    /** @public */
    class TemperatureSensor extends TemperatureSensorBase {
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 10:
            if (bp.entryCount > 1) this.data.dataInterval = bp.getNumber(1);else this.data.dataInterval = bp.getNumber(0);
            this._FIREPropertyChange('DataInterval');
            this._FIREPropertyChange('DataRate');
            break;
          case 76:
            this.data.temperature = 1e+300;
            super._bridgeInput(bp);
            break;
          case 84:
            super._bridgeInput(bp);
            this.data.temperature = 1e+300;
            switch (this.data.thermocoupleType) {
              case exports.ThermocoupleType.J:
                this.data.minTemperature = 0;
                this.data.maxTemperature = 750;
                break;
              case exports.ThermocoupleType.K:
                this.data.minTemperature = -200;
                this.data.maxTemperature = 1250;
                break;
              case exports.ThermocoupleType.E:
                this.data.minTemperature = -200;
                this.data.maxTemperature = 900;
                break;
              case exports.ThermocoupleType.T:
                this.data.minTemperature = -200;
                this.data.maxTemperature = 350;
                break;
            }
            this._FIREPropertyChange('MinTemperature', bp);
            this._FIREPropertyChange('MaxTemperature', bp);
            break;
          case 180:
            this.data.RTDWireSetup = bp.entries[0].v;
            this._FIREPropertyChange('RTDWireSetup', bp);
            break;
          default:
            super._bridgeInput(bp);
            break;
        }
      }
      /** @internal */
      _errorHandler(code) {
        switch (code) {
          case exports.ErrorEventCode.SATURATION:
          case exports.ErrorEventCode.OUT_OF_RANGE:
            this.data.temperature = 1e+300;
            this._gotTemperatureChangeErrorEvent = true;
            break;
        }
      }
    }

    /**
     * The Voltage Input class measures the voltage across the input of a Phidget with a voltage input. This may be a sensor designed to measure voltage directly, or it could be an input designed to interface with 0-5V sensors.
     *
     * For 0-5V sensors, this class supports conversion to sensor data with units specific to the Phidget sensor being used, to make reading these sensors easy.
     * @public
     */
    class VoltageInputBase extends PhidgetChannel {
      /** @internal */
      data;
      onVoltageChange = null;
      /** @internal */
      _gotVoltageChangeErrorEvent;
      onSensorChange = null;
      /** @internal */
      _gotSensorChangeErrorEvent;
      constructor(ch) {
        super(ch);
        this._class = exports.ChannelClass.VOLTAGE_INPUT;
        this.name = "VoltageInput";
        this.data = this._initData();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 54:
            if (bp.entryCount > 1) this.data.dataInterval = bp.entries[1].v;else this.data.dataInterval = bp.entries[0].v;
            this._FIREPropertyChange('DataInterval', bp);
            this._FIREPropertyChange('DataRate', bp);
            break;
          case 74:
            this.data.powerSupply = bp.entries[0].v;
            this._FIREPropertyChange('PowerSupply', bp);
            break;
          case 79:
            this.data.sensorType = bp.entries[0].v;
            this._FIREPropertyChange('SensorType', bp);
            break;
          case 122:
            this.data.sensorValueChangeTrigger = bp.entries[0].v;
            this._FIREPropertyChange('SensorValueChangeTrigger', bp);
            break;
          case 46:
            this.data.voltageChangeTrigger = bp.entries[0].v;
            this._FIREPropertyChange('VoltageChangeTrigger', bp);
            break;
          case 87:
            this.data.voltageRange = bp.entries[0].v;
            this._FIREPropertyChange('VoltageRange', bp);
            break;
          case 115:
            {
              this.data.sensorValue = bp.entries[0].v;
              const sensorUnit = {
                unit: bp.entries["UnitInfo.unit"].v,
                name: bp.entries["UnitInfo.name"].v,
                symbol: bp.entries["UnitInfo.symbol"].v
              };
              this.data.sensorUnit = sensorUnit;
              if (this._isAttachedDone && this.onSensorChange) {
                try {
                  this.onSensorChange(this.data.sensorValue, this.data.sensorUnit);
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          default:
            throw new PhidgetError(exports.ErrorCode.INVALID_PACKET, "Unsupported bridge packet: 0x" + bp.vpkt.toString(16));
        }
      }
      /** @internal */
      _initData() {
        return {
          dataInterval: 1e+300,
          minDataInterval: 4294967295,
          maxDataInterval: 4294967295,
          minDataRate: 1e+300,
          maxDataRate: 1e+300,
          powerSupply: 2147483647,
          sensorType: 2147483647,
          sensorUnit: null,
          sensorValue: 1e+300,
          voltage: 1e+300,
          minVoltage: 1e+300,
          maxVoltage: 1e+300,
          voltageChangeTrigger: 1e+300,
          minVoltageChangeTrigger: 1e+300,
          maxVoltageChangeTrigger: 1e+300,
          voltageRange: 2147483647,
          sensorValueChangeTrigger: 1e+300
        };
      }
      /** @internal */
      _initAfterOpen() {}
      /** @internal */
      async _setDefaults() {}
      /** @internal */
      _hasInitialState() {
        return true;
      }
      /** @internal */
      _fireInitialEvents() {}
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between events can also be affected by the change trigger.
       * @throws `PhidgetError`
       */
      get dataInterval() {
        return this.getDataInterval();
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get minDataInterval() {
        return this.getMinDataInterval();
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataInterval() {
        return this.getMaxDataInterval();
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       */
      get dataRate() {
        return this.getDataRate();
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get minDataRate() {
        return this.getMinDataRate();
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataRate() {
        return this.getMaxDataRate();
      }
      /**
       * Choose the power supply voltage.
       *
       * *   Set this to the voltage specified in the attached sensor's data sheet to power it.
       * *   Set to `phidget22.PowerSupply.OFF` to turn off the supply to save power.
       * @throws `PhidgetError`
       */
      get powerSupply() {
        return this.getPowerSupply();
      }
      /**
       * We sell a variety of analog sensors that do not have their own API, they simply output a voltage that can be converted to a digital value using a specific formula. By matching the `sensorType` to your analog sensor, the correct formula will automatically be applied to data when you get the `sensorValue` or subscribe to the `SensorChange` event.
       *
       * *   The `SensorChange` event has its own change trigger associated with it: `sensorValueChangeTrigger`.
       * *   Any data from getting the `sensorValue` or subscribing to the `SensorChange` event will have a `sensorUnit` associated with it.
       *
       * **Note:** Unlike other properties such as `Phidget.deviceSerialNumber` or `Phidget.channel`, `sensorType` is set after the device is opened, not before.
       * @throws `PhidgetError`
       */
      get sensorType() {
        return this.getSensorType();
      }
      /**
       * The unit of measurement that applies to the sensor values of the `sensorType` that has been selected.
       *
       * *   Helps keep track of the type of information being calculated from the voltage input.
       * @throws `PhidgetError`
       */
      get sensorUnit() {
        return this.getSensorUnit();
      }
      /**
       * The most recent sensor value that the channel has reported.
       *
       * *   Use `sensorUnit` to get the measurement units that are associated with the `sensorValue`
       * @throws `PhidgetError`
       */
      get sensorValue() {
        return this.getSensorValue();
      }
      /**
       * The channel will not issue a `SensorChange` event until the sensor value has changed by the amount specified by the `sensorValueChangeTrigger`.
       *
       * *   Setting the `sensorValueChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @throws `PhidgetError`
       */
      get sensorValueChangeTrigger() {
        return this.getSensorValueChangeTrigger();
      }
      /**
       * The most recent voltage value that the channel has reported.
       *
       * *   This value will always be between `minVoltage` and `maxVoltage`.
       * @throws `PhidgetError`
       */
      get voltage() {
        return this.getVoltage();
      }
      /**
       * The minimum value the `VoltageChange` event will report.
       * @throws `PhidgetError`
       */
      get minVoltage() {
        return this.getMinVoltage();
      }
      /**
       * The maximum value the `VoltageChange` event will report.
       * @throws `PhidgetError`
       */
      get maxVoltage() {
        return this.getMaxVoltage();
      }
      /**
       * The channel will not issue a `VoltageChange` event until the voltage value has changed by the amount specified by the `voltageChangeTrigger`.
       *
       * *   Setting the `voltageChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @throws `PhidgetError`
       */
      get voltageChangeTrigger() {
        return this.getVoltageChangeTrigger();
      }
      /**
       * The minimum value that `voltageChangeTrigger` can be set to.
       * @throws `PhidgetError`
       */
      get minVoltageChangeTrigger() {
        return this.getMinVoltageChangeTrigger();
      }
      /**
       * The maximum value that `voltageChangeTrigger` can be set to.
       * @throws `PhidgetError`
       */
      get maxVoltageChangeTrigger() {
        return this.getMaxVoltageChangeTrigger();
      }
      /**
       * The voltage range you choose should allow you to measure the full range of your input signal.
       *
       * *   A larger `voltageRange` equates to less resolution.
       * *   If a `Saturation` event occurs, increase the voltage range.
       * @throws `PhidgetError`
       */
      get voltageRange() {
        return this.getVoltageRange();
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between events can also be affected by the change trigger.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getDataInterval() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.dataInterval;
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between events can also be affected by the change trigger.
       * @throws `PhidgetError`
       * @param dataInterval - The data interval value
       */
      async setDataInterval(dataInterval) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: dataInterval
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMinDataInterval() {
        this._assertOpen();
        if (this.data.minDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataInterval;
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMaxDataInterval() {
        this._assertOpen();
        if (this.data.maxDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @returns The data rate for the channel
       * @throws `PhidgetError`
       */
      getDataRate() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return 1000.0 / this.data.dataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       * @param dataRate - The data rate for the channel
       */
      async setDataRate(dataRate) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: Math.round(1000.0 / dataRate)
        });
        bp.set({
          name: "1",
          type: "g",
          value: 1000.0 / dataRate
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMinDataRate() {
        this._assertOpen();
        if (this.data.minDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataRate;
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMaxDataRate() {
        this._assertOpen();
        if (this.data.maxDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataRate;
      }
      /**
       * Choose the power supply voltage.
       *
       * *   Set this to the voltage specified in the attached sensor's data sheet to power it.
       * *   Set to `phidget22.PowerSupply.OFF` to turn off the supply to save power.
       * @returns The power supply value
       * @throws `PhidgetError`
       */
      getPowerSupply() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 232:
          case 236:
          case 240:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.powerSupply === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.powerSupply;
      }
      /**
       * Choose the power supply voltage.
       *
       * *   Set this to the voltage specified in the attached sensor's data sheet to power it.
       * *   Set to `phidget22.PowerSupply.OFF` to turn off the supply to save power.
       * @throws `PhidgetError`
       * @param powerSupply - The power supply value
       */
      async setPowerSupply(powerSupply) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: powerSupply
        });
        await bp.send(this._ch, 74);
      }
      /**
       * We sell a variety of analog sensors that do not have their own API, they simply output a voltage that can be converted to a digital value using a specific formula. By matching the `sensorType` to your analog sensor, the correct formula will automatically be applied to data when you get the `sensorValue` or subscribe to the `SensorChange` event.
       *
       * *   The `SensorChange` event has its own change trigger associated with it: `sensorValueChangeTrigger`.
       * *   Any data from getting the `sensorValue` or subscribing to the `SensorChange` event will have a `sensorUnit` associated with it.
       *
       * **Note:** Unlike other properties such as `Phidget.deviceSerialNumber` or `Phidget.channel`, `sensorType` is set after the device is opened, not before.
       * @returns The sensor type value
       * @throws `PhidgetError`
       */
      getSensorType() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 19:
          case 29:
          case 33:
          case 11:
          case 15:
          case 175:
          case 182:
          case 187:
          case 191:
          case 473:
          case 474:
          case 475:
          case 216:
          case 224:
          case 226:
          case 228:
          case 232:
          case 236:
          case 240:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.sensorType === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.sensorType;
      }
      /**
       * We sell a variety of analog sensors that do not have their own API, they simply output a voltage that can be converted to a digital value using a specific formula. By matching the `sensorType` to your analog sensor, the correct formula will automatically be applied to data when you get the `sensorValue` or subscribe to the `SensorChange` event.
       *
       * *   The `SensorChange` event has its own change trigger associated with it: `sensorValueChangeTrigger`.
       * *   Any data from getting the `sensorValue` or subscribing to the `SensorChange` event will have a `sensorUnit` associated with it.
       *
       * **Note:** Unlike other properties such as `Phidget.deviceSerialNumber` or `Phidget.channel`, `sensorType` is set after the device is opened, not before.
       * @throws `PhidgetError`
       * @param sensorType - The sensor type value
       */
      async setSensorType(sensorType) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: sensorType
        });
        await bp.send(this._ch, 79);
      }
      /**
       * The unit of measurement that applies to the sensor values of the `sensorType` that has been selected.
       *
       * *   Helps keep track of the type of information being calculated from the voltage input.
       * @returns The sensor unit information corresponding to the `sensorValue`.
       * @throws `PhidgetError`
       */
      getSensorUnit() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 19:
          case 29:
          case 33:
          case 11:
          case 15:
          case 175:
          case 182:
          case 187:
          case 191:
          case 473:
          case 474:
          case 475:
          case 216:
          case 224:
          case 226:
          case 228:
          case 232:
          case 236:
          case 240:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.sensorUnit === null) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.sensorUnit;
      }
      /**
       * The most recent sensor value that the channel has reported.
       *
       * *   Use `sensorUnit` to get the measurement units that are associated with the `sensorValue`
       * @returns The sensor value
       * @throws `PhidgetError`
       */
      getSensorValue() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 19:
          case 29:
          case 33:
          case 11:
          case 15:
          case 175:
          case 182:
          case 187:
          case 191:
          case 473:
          case 474:
          case 475:
          case 216:
          case 224:
          case 226:
          case 228:
          case 232:
          case 236:
          case 240:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.sensorValue === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.sensorValue;
      }
      /**
       * The channel will not issue a `SensorChange` event until the sensor value has changed by the amount specified by the `sensorValueChangeTrigger`.
       *
       * *   Setting the `sensorValueChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getSensorValueChangeTrigger() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 19:
          case 29:
          case 33:
          case 11:
          case 15:
          case 175:
          case 182:
          case 187:
          case 191:
          case 473:
          case 474:
          case 475:
          case 216:
          case 224:
          case 226:
          case 228:
          case 232:
          case 236:
          case 240:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.sensorValueChangeTrigger === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.sensorValueChangeTrigger;
      }
      /**
       * The channel will not issue a `SensorChange` event until the sensor value has changed by the amount specified by the `sensorValueChangeTrigger`.
       *
       * *   Setting the `sensorValueChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @throws `PhidgetError`
       * @param sensorValueChangeTrigger - The change trigger value
       */
      async setSensorValueChangeTrigger(sensorValueChangeTrigger) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: sensorValueChangeTrigger
        });
        await bp.send(this._ch, 122);
      }
      /**
       * The most recent voltage value that the channel has reported.
       *
       * *   This value will always be between `minVoltage` and `maxVoltage`.
       * @returns The voltage value
       * @throws `PhidgetError`
       */
      getVoltage() {
        this._assertOpen();
        if (this.data.voltage === 1e+300 || Number.isNaN(this.data.voltage)) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        if (this.data.voltage > this.data.maxVoltage) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE_HIGH);
        if (this.data.voltage < this.data.minVoltage) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE_LOW);
        return this.data.voltage;
      }
      /**
       * The minimum value the `VoltageChange` event will report.
       * @returns The voltage value
       * @throws `PhidgetError`
       */
      getMinVoltage() {
        this._assertOpen();
        if (this.data.minVoltage === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minVoltage;
      }
      /**
       * The maximum value the `VoltageChange` event will report.
       * @returns The voltage value
       * @throws `PhidgetError`
       */
      getMaxVoltage() {
        this._assertOpen();
        if (this.data.maxVoltage === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxVoltage;
      }
      /**
       * The channel will not issue a `VoltageChange` event until the voltage value has changed by the amount specified by the `voltageChangeTrigger`.
       *
       * *   Setting the `voltageChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getVoltageChangeTrigger() {
        this._assertOpen();
        if (this.data.voltageChangeTrigger === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.voltageChangeTrigger;
      }
      /**
       * The channel will not issue a `VoltageChange` event until the voltage value has changed by the amount specified by the `voltageChangeTrigger`.
       *
       * *   Setting the `voltageChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @throws `PhidgetError`
       * @param voltageChangeTrigger - The change trigger value
       */
      async setVoltageChangeTrigger(voltageChangeTrigger) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: voltageChangeTrigger
        });
        await bp.send(this._ch, 46);
      }
      /**
       * The minimum value that `voltageChangeTrigger` can be set to.
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getMinVoltageChangeTrigger() {
        this._assertOpen();
        if (this.data.minVoltageChangeTrigger === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minVoltageChangeTrigger;
      }
      /**
       * The maximum value that `voltageChangeTrigger` can be set to.
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getMaxVoltageChangeTrigger() {
        this._assertOpen();
        if (this.data.maxVoltageChangeTrigger === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxVoltageChangeTrigger;
      }
      /**
       * The voltage range you choose should allow you to measure the full range of your input signal.
       *
       * *   A larger `voltageRange` equates to less resolution.
       * *   If a `Saturation` event occurs, increase the voltage range.
       * @returns The voltage range value
       * @throws `PhidgetError`
       */
      getVoltageRange() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 216:
          case 460:
          case 461:
          case 462:
          case 463:
          case 464:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.voltageRange === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.voltageRange;
      }
      /**
       * The voltage range you choose should allow you to measure the full range of your input signal.
       *
       * *   A larger `voltageRange` equates to less resolution.
       * *   If a `Saturation` event occurs, increase the voltage range.
       * @throws `PhidgetError`
       * @param voltageRange - The voltage range value
       */
      async setVoltageRange(voltageRange) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: voltageRange
        });
        await bp.send(this._ch, 87);
      }
    }

    const Units = [{
      unit: exports.Unit.NONE,
      name: "none",
      symbol: ""
    }, {
      unit: exports.Unit.BOOLEAN,
      name: "boolean",
      symbol: ""
    }, {
      unit: exports.Unit.PERCENT,
      name: "percent",
      symbol: "%"
    }, {
      unit: exports.Unit.DECIBEL,
      name: "decibel",
      symbol: "dB"
    }, {
      unit: exports.Unit.MILLIMETER,
      name: "millimeter",
      symbol: "mm"
    }, {
      unit: exports.Unit.CENTIMETER,
      name: "centimeter",
      symbol: "cm"
    }, {
      unit: exports.Unit.METER,
      name: "meter",
      symbol: "m"
    }, {
      unit: exports.Unit.GRAM,
      name: "gram",
      symbol: "g"
    }, {
      unit: exports.Unit.KILOGRAM,
      name: "kilogram",
      symbol: "kg"
    }, {
      unit: exports.Unit.MILLIAMPERE,
      name: "milliampere",
      symbol: "mA"
    }, {
      unit: exports.Unit.AMPERE,
      name: "ampere",
      symbol: "A"
    }, {
      unit: exports.Unit.KILOPASCAL,
      name: "kilopascal",
      symbol: "kPa"
    }, {
      unit: exports.Unit.VOLT,
      name: "volt",
      symbol: "V"
    }, {
      unit: exports.Unit.DEGREE_CELCIUS,
      name: "degree Celsius",
      symbol: "\xB0C"
    }, {
      unit: exports.Unit.LUX,
      name: "lux",
      symbol: "lx"
    }, {
      unit: exports.Unit.GAUSS,
      name: "gauss",
      symbol: "G"
    }, {
      unit: exports.Unit.PH,
      name: "pH",
      symbol: ""
    }, {
      unit: exports.Unit.WATT,
      name: "watt",
      symbol: "W"
    }];

    /** @internal */
    function makeMOT2002Support() {
      return {
        voltageBuffer: [],
        voltageBufferIndex: 0,
        voltageBufferReady: false,
        motionSensorCountdown: 0,
        motionSensorBaseline: 1e+300,
        VOLTAGE_BUFFER_LEN: 25
      };
    }
    /** @public */
    class VoltageInput extends VoltageInputBase {
      constructor(ch) {
        super(ch);
        this._MOT2002Support = makeMOT2002Support();
      }
      /** @internal */
      _MOT2002Support;
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 10:
            if (bp.entryCount > 1) this.data.dataInterval = bp.getNumber(1);else this.data.dataInterval = bp.getNumber(0);
            this._FIREPropertyChange('DataInterval', bp);
            this._FIREPropertyChange('DataRate', bp);
            break;
          case 27:
            this.data.minDataInterval = bp.getNumber(0);
            this._FIREPropertyChange('MinDataInterval', bp);
            break;
          case 79:
            super._bridgeInput(bp);
            this._bangSensorVoltage();
            switch (this.data.sensorType) {
              case exports.VoltageSensorType.PN_MOT2002_LOW:
              case exports.VoltageSensorType.PN_MOT2002_MED:
              case exports.VoltageSensorType.PN_MOT2002_HIGH:
                {
                  const subbp = new BridgePacket();
                  subbp.set({
                    name: '0',
                    type: 'u',
                    value: 200
                  });
                  subbp.sendToChannel(this._ch, 54);
                  break;
                }
            }
            break;
          case 101:
            {
              this.data.voltage = bp.getNumber('0');
              this._updateVoltageBuffer(this.data.voltage);
              const sentSensorEvent = this._bangSensorVoltage(true);
              if (sentSensorEvent && this._ch.conn._isRemote) throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
              break;
            }
          case 87:
            super._bridgeInput(bp);
            switch (this.data.voltageRange) {
              case exports.VoltageRange.MILLIVOLTS_10:
                this.data.minVoltage = -0.01;
                this.data.maxVoltage = 0.01;
                break;
              case exports.VoltageRange.MILLIVOLTS_40:
                this.data.minVoltage = -0.04;
                this.data.maxVoltage = 0.04;
                break;
              case exports.VoltageRange.MILLIVOLTS_200:
                this.data.minVoltage = -0.2;
                this.data.maxVoltage = 0.2;
                break;
              case exports.VoltageRange.MILLIVOLTS_312_5:
                this.data.minVoltage = -0.3125;
                this.data.maxVoltage = 0.3125;
                break;
              case exports.VoltageRange.MILLIVOLTS_400:
                this.data.minVoltage = -0.4;
                this.data.maxVoltage = 0.4;
                break;
              case exports.VoltageRange.MILLIVOLTS_1000:
                this.data.minVoltage = -1;
                this.data.maxVoltage = 1.0;
                break;
              case exports.VoltageRange.VOLTS_2:
                this.data.minVoltage = -2;
                this.data.maxVoltage = 2.0;
                break;
              case exports.VoltageRange.VOLTS_5:
                this.data.minVoltage = -5;
                this.data.maxVoltage = 5.0;
                break;
              case exports.VoltageRange.VOLTS_15:
                this.data.minVoltage = -15;
                this.data.maxVoltage = 15.0;
                break;
              case exports.VoltageRange.VOLTS_40:
                this.data.minVoltage = -40;
                this.data.maxVoltage = 40.0;
                break;
              case exports.VoltageRange.AUTO:
                switch (this._ch?.chDef.uid) {
                  case 458:
                  case 459:
                  case 461:
                  case 462:
                    this.data.minVoltage = -40;
                    this.data.maxVoltage = 40.0;
                    break;
                  case 463:
                  case 464:
                    this.data.minVoltage = -1;
                    this.data.maxVoltage = 1.0;
                    break;
                }
            }
            this._FIREPropertyChange('MinVoltage', bp);
            this._FIREPropertyChange('MaxVoltage', bp);
            break;
          case 181:
            this.data.powerSupply = bp.entries[0].v;
            this._FIREPropertyChange('PowerSupply', bp);
            break;
          default:
            super._bridgeInput(bp);
            break;
        }
      }
      /** @internal */
      _errorHandler(code) {
        switch (code) {
          case exports.ErrorEventCode.SATURATION:
            this.data.voltage = 1e+300;
            this.data.sensorValue = 1e+300;
            this._gotVoltageChangeErrorEvent = true;
            break;
        }
      }
      /** @internal */
      _initAfterOpen() {
        super._initAfterOpen();
        this._MOT2002Support = makeMOT2002Support();
        if (this.data.sensorType === 2147483647) this.data.sensorType = exports.VoltageSensorType.VOLTAGE;
        this.data.sensorUnit = this._getVoltageSensorUnit(this.data.sensorType);
        this.data.sensorValue = this._getVoltageSensorValue(this.data.voltage, this.data.sensorType);
      }
      /** @internal */
      _hasInitialState() {
        if (this.data.voltage == 1e+300 && !this._gotVoltageChangeErrorEvent) return false;
        return super._hasInitialState();
      }
      /** @internal */
      _fireInitialEvents() {
        if (this.data.sensorType != exports.VoltageSensorType.VOLTAGE) {
          if (this.data.sensorValue != 1e+300 && this.data.sensorUnit != null) if (this.onSensorChange) {
            try {
              this.onSensorChange(this.data.sensorValue, this.data.sensorUnit);
            } catch (err) {
              logEventException(err);
            }
          }
        } else {
          if (this.data.voltage != 1e+300) if (this.onVoltageChange) {
            try {
              this.onVoltageChange(this.data.voltage);
            } catch (err) {
              logEventException(err);
            }
          }
        }
        super._fireInitialEvents();
      }
      /** @internal */
      _bangSensorVoltage(includeVoltage = false) {
        let sensorValue;
        let unitInfo;
        let sentSensorEvent = false;
        if (this._ch.supportedBridgePacket(115) && this._ch.conn._isLocal && this.data.sensorType !== exports.VoltageSensorType.VOLTAGE) {
          sensorValue = this._getVoltageSensorValue(this.data.voltage, this.data.sensorType);
          if (!this._getSensorValueInRange(sensorValue, this.data.sensorType)) {
            this.data.sensorValue = 1e+300;
            if (this._isAttachedDone) {
              const bp = new BridgePacket();
              bp.set({
                name: '0',
                type: 'd',
                value: exports.ErrorEventCode.OUT_OF_RANGE
              });
              bp.set({
                name: '1',
                type: 's',
                value: 'Sensor value is outside the valid range for this sensor.'
              });
              this._ch.sendErrorEvent(bp);
            }
          } else if (this.data.sensorValue === 1e+300 || Math.abs(sensorValue - this.data.sensorValue) >= this.data.sensorValueChangeTrigger) {
            this.data.sensorValue = sensorValue;
            if (this._isAttachedDone) {
              unitInfo = this._getVoltageSensorUnit(this.data.sensorType);
              const bp = new BridgePacket();
              bp.set({
                name: '0',
                type: 'g',
                value: sensorValue
              });
              bp.set({
                name: 'UnitInfo.unit',
                type: 'g',
                value: unitInfo.unit
              });
              bp.set({
                name: 'UnitInfo.name',
                type: 's',
                value: unitInfo.name
              });
              bp.set({
                name: 'UnitInfo.symbol',
                type: 's',
                value: unitInfo.symbol
              });
              bp.sendToChannel(this._ch, 115);
            }
          }
          sentSensorEvent = true;
        } else if (includeVoltage) {
          this.data.sensorUnit = this._getVoltageSensorUnit(this.data.sensorType);
          this.data.sensorValue = this._getVoltageSensorValue(this.data.voltage, this.data.sensorType);
          if (this._isAttachedDone && this.onVoltageChange) {
            try {
              this.onVoltageChange(this.data.voltage);
            } catch (err) {
              logEventException(err);
            }
          }
        }
        return sentSensorEvent;
      }
      /** @internal */
      _updateVoltageBuffer(voltage) {
        this._MOT2002Support.voltageBuffer.push(voltage);
        if (this._MOT2002Support.voltageBuffer.length >= this._MOT2002Support.VOLTAGE_BUFFER_LEN) {
          this._MOT2002Support.voltageBufferReady = true;
          if (this._MOT2002Support.voltageBuffer.length > this._MOT2002Support.VOLTAGE_BUFFER_LEN) this._MOT2002Support.voltageBuffer.shift();
        }
      }
      /** @internal */
      _getVoltageSensorValue(voltage, sensorType) {
        if (voltage === 1e+300) return 1e+300;
        switch (sensorType) {
          case exports.VoltageSensorType.PN_1114:
            return RoundDouble(voltage / 0.02 - 50, 3);
          case exports.VoltageSensorType.PN_1117:
            return RoundDouble(voltage * 12 - 30, 3);
          case exports.VoltageSensorType.PN_1123:
            return RoundDouble(voltage * 12 - 30, 3);
          case exports.VoltageSensorType.PN_1127:
            return RoundDouble(voltage * 200, 2);
          case exports.VoltageSensorType.PN_1130_PH:
            return RoundDouble(voltage * 3.56 - 1.889, 4);
          case exports.VoltageSensorType.PN_1130_ORP:
            return RoundDouble((2.5 - voltage) / 1.037, 5);
          case exports.VoltageSensorType.PN_1132:
            return RoundDouble(voltage / 0.225, 4);
          case exports.VoltageSensorType.PN_1133:
            return RoundDouble(16.801 * Math.log(voltage * 200) + 9.872, 4);
          case exports.VoltageSensorType.PN_1135:
            return RoundDouble((voltage - 2.5) / 0.0681, 3);
          case exports.VoltageSensorType.PN_1142:
            return RoundDouble(voltage * 295.7554 + 33.67076, 2);
          case exports.VoltageSensorType.PN_1143:
            return RoundDouble(Math.exp(voltage * 4.77 - 0.56905), 4);
          case exports.VoltageSensorType.PN_3500:
            return RoundDouble(voltage / 0.5, 4);
          case exports.VoltageSensorType.PN_3501:
            return RoundDouble(voltage / 0.2, 4);
          case exports.VoltageSensorType.PN_3502:
            return RoundDouble(voltage / 0.1, 4);
          case exports.VoltageSensorType.PN_3503:
            return RoundDouble(voltage / 0.05, 3);
          case exports.VoltageSensorType.PN_3507:
            return RoundDouble(voltage * 50, 3);
          case exports.VoltageSensorType.PN_3508:
            return RoundDouble(voltage * 50, 3);
          case exports.VoltageSensorType.PN_3509:
            return RoundDouble(voltage * 40, 3);
          case exports.VoltageSensorType.PN_3510:
            return RoundDouble(voltage * 15, 4);
          case exports.VoltageSensorType.PN_3511:
            return RoundDouble(voltage * 2, 4);
          case exports.VoltageSensorType.PN_3512:
            return RoundDouble(voltage * 20, 3);
          case exports.VoltageSensorType.PN_3513:
            return RoundDouble(voltage * 200, 2);
          case exports.VoltageSensorType.PN_3514:
            return RoundDouble(voltage * 1500, 1);
          case exports.VoltageSensorType.PN_3515:
            return RoundDouble(voltage * 1500, 1);
          case exports.VoltageSensorType.PN_3516:
            return RoundDouble(voltage * 250, 2);
          case exports.VoltageSensorType.PN_3517:
            return RoundDouble(voltage * 250, 2);
          case exports.VoltageSensorType.PN_3518:
            return RoundDouble(voltage * 110, 3);
          case exports.VoltageSensorType.PN_3519:
            return RoundDouble(voltage * 330, 2);
          case exports.VoltageSensorType.PN_3584:
            return RoundDouble(voltage * 10, 4);
          case exports.VoltageSensorType.PN_3585:
            return RoundDouble(voltage * 20, 3);
          case exports.VoltageSensorType.PN_3586:
            return RoundDouble(voltage * 50, 3);
          case exports.VoltageSensorType.PN_3587:
            return RoundDouble(voltage * 20 - 50, 3);
          case exports.VoltageSensorType.PN_3588:
            return RoundDouble(voltage * 40 - 100, 3);
          case exports.VoltageSensorType.PN_3589:
            return RoundDouble(voltage * 100 - 250, 3);
          case exports.VoltageSensorType.PN_MOT2002_LOW:
            return this._doMotionSensorCalculations(0.8) ? 1 : 0;
          case exports.VoltageSensorType.PN_MOT2002_MED:
            return this._doMotionSensorCalculations(0.4) ? 1 : 0;
          case exports.VoltageSensorType.PN_MOT2002_HIGH:
            return this._doMotionSensorCalculations(0.04) ? 1 : 0;
          case exports.VoltageSensorType.PN_VCP4114:
            return RoundDouble((voltage - 2.5) / 0.0625, 3);
          case exports.VoltageSensorType.VOLTAGE:
          default:
            return voltage;
        }
      }
      /** @internal */
      _getSensorValueInRange(sensorValue, sensorType) {
        if (sensorValue === 1e+300) {
          return false;
        }
        switch (sensorType) {
          case exports.VoltageSensorType.PN_1114:
            return sensorValue >= -40 && sensorValue <= 125.0;
          case exports.VoltageSensorType.PN_1117:
            return sensorValue >= -30 && sensorValue <= 30.0;
          case exports.VoltageSensorType.PN_1123:
            return sensorValue >= -30 && sensorValue <= 30.0;
          case exports.VoltageSensorType.PN_1127:
            return sensorValue >= 0.0 && sensorValue <= 1000.0;
          case exports.VoltageSensorType.PN_1130_PH:
            return sensorValue >= 0.0 && sensorValue <= 14.0;
          case exports.VoltageSensorType.PN_1130_ORP:
            return sensorValue >= -2 && sensorValue <= 2.0;
          case exports.VoltageSensorType.PN_1132:
            return sensorValue >= 4.0 && sensorValue <= 20.0;
          case exports.VoltageSensorType.PN_1133:
            return sensorValue >= 50.0 && sensorValue <= 100.0;
          case exports.VoltageSensorType.PN_1135:
            return sensorValue >= -30 && sensorValue <= 30.0;
          case exports.VoltageSensorType.PN_1142:
            return sensorValue >= 0.0 && sensorValue <= 1000.0;
          case exports.VoltageSensorType.PN_1143:
            return sensorValue >= 0.0 && sensorValue <= 70000.0;
          case exports.VoltageSensorType.PN_3500:
            return sensorValue >= 0.0 && sensorValue <= 10.0;
          case exports.VoltageSensorType.PN_3501:
            return sensorValue >= 0.0 && sensorValue <= 25.0;
          case exports.VoltageSensorType.PN_3502:
            return sensorValue >= 0.0 && sensorValue <= 50.0;
          case exports.VoltageSensorType.PN_3503:
            return sensorValue >= 0.0 && sensorValue <= 100.0;
          case exports.VoltageSensorType.PN_3507:
            return sensorValue >= 0.0 && sensorValue <= 250.0;
          case exports.VoltageSensorType.PN_3508:
            return sensorValue >= 0.0 && sensorValue <= 250.0;
          case exports.VoltageSensorType.PN_3509:
            return sensorValue >= 0.0 && sensorValue <= 200.0;
          case exports.VoltageSensorType.PN_3510:
            return sensorValue >= 0.0 && sensorValue <= 75.0;
          case exports.VoltageSensorType.PN_3511:
            return sensorValue >= 0.0 && sensorValue <= 10.0;
          case exports.VoltageSensorType.PN_3512:
            return sensorValue >= 0.0 && sensorValue <= 100.0;
          case exports.VoltageSensorType.PN_3513:
            return sensorValue >= 0.0 && sensorValue <= 1000.0;
          case exports.VoltageSensorType.PN_3514:
            return sensorValue >= 0.0 && sensorValue <= 7500.0;
          case exports.VoltageSensorType.PN_3515:
            return sensorValue >= 0.0 && sensorValue <= 7500.0;
          case exports.VoltageSensorType.PN_3516:
            return sensorValue >= 0.0 && sensorValue <= 1250.0;
          case exports.VoltageSensorType.PN_3517:
            return sensorValue >= 0.0 && sensorValue <= 1250.0;
          case exports.VoltageSensorType.PN_3518:
            return sensorValue >= 0.0 && sensorValue <= 550.0;
          case exports.VoltageSensorType.PN_3519:
            return sensorValue >= 0.0 && sensorValue <= 1650.0;
          case exports.VoltageSensorType.PN_3584:
            return sensorValue >= 0.0 && sensorValue <= 50.0;
          case exports.VoltageSensorType.PN_3585:
            return sensorValue >= 0.0 && sensorValue <= 100.0;
          case exports.VoltageSensorType.PN_3586:
            return sensorValue >= 0.0 && sensorValue <= 250.0;
          case exports.VoltageSensorType.PN_3587:
            return sensorValue >= -50 && sensorValue <= 50.0;
          case exports.VoltageSensorType.PN_3588:
            return sensorValue >= -100 && sensorValue <= 100.0;
          case exports.VoltageSensorType.PN_3589:
            return sensorValue >= -250 && sensorValue <= 250.0;
          case exports.VoltageSensorType.PN_MOT2002_LOW:
          case exports.VoltageSensorType.PN_MOT2002_MED:
          case exports.VoltageSensorType.PN_MOT2002_HIGH:
            return this._MOT2002Support.motionSensorBaseline !== 1e+300;
          case exports.VoltageSensorType.PN_VCP4114:
            return sensorValue >= -25 && sensorValue <= 25.0;
          case exports.VoltageSensorType.VOLTAGE:
          default:
            return true;
        }
      }
      /** @internal */
      _getVoltageSensorUnit(sensorType) {
        switch (sensorType) {
          case exports.VoltageSensorType.PN_1130_PH:
            return Units[exports.Unit.PH];
          case exports.VoltageSensorType.PN_1114:
            return Units[exports.Unit.DEGREE_CELCIUS];
          case exports.VoltageSensorType.PN_1127:
          case exports.VoltageSensorType.PN_1142:
          case exports.VoltageSensorType.PN_1143:
            return Units[exports.Unit.LUX];
          case exports.VoltageSensorType.PN_1132:
          case exports.VoltageSensorType.PN_3511:
          case exports.VoltageSensorType.PN_3512:
          case exports.VoltageSensorType.PN_3513:
            return Units[exports.Unit.MILLIAMPERE];
          case exports.VoltageSensorType.PN_1133:
            return Units[exports.Unit.DECIBEL];
          case exports.VoltageSensorType.PN_3500:
          case exports.VoltageSensorType.PN_3501:
          case exports.VoltageSensorType.PN_3502:
          case exports.VoltageSensorType.PN_3503:
          case exports.VoltageSensorType.PN_3584:
          case exports.VoltageSensorType.PN_3585:
          case exports.VoltageSensorType.PN_3586:
          case exports.VoltageSensorType.PN_3587:
          case exports.VoltageSensorType.PN_3588:
          case exports.VoltageSensorType.PN_3589:
          case exports.VoltageSensorType.PN_VCP4114:
            return Units[exports.Unit.AMPERE];
          case exports.VoltageSensorType.PN_3514:
          case exports.VoltageSensorType.PN_3515:
          case exports.VoltageSensorType.PN_3516:
          case exports.VoltageSensorType.PN_3517:
          case exports.VoltageSensorType.PN_3518:
          case exports.VoltageSensorType.PN_3519:
            return Units[exports.Unit.WATT];
          case exports.VoltageSensorType.PN_MOT2002_LOW:
          case exports.VoltageSensorType.PN_MOT2002_MED:
          case exports.VoltageSensorType.PN_MOT2002_HIGH:
            return Units[exports.Unit.BOOLEAN];
          case exports.VoltageSensorType.PN_1117:
          case exports.VoltageSensorType.PN_1123:
          case exports.VoltageSensorType.PN_1130_ORP:
          case exports.VoltageSensorType.PN_1135:
          case exports.VoltageSensorType.PN_3507:
          case exports.VoltageSensorType.PN_3508:
          case exports.VoltageSensorType.PN_3509:
          case exports.VoltageSensorType.PN_3510:
          case exports.VoltageSensorType.VOLTAGE:
          default:
            return Units[exports.Unit.VOLT];
        }
      }
      /** @internal */
      _doMotionSensorCalculations(threshold) {
        const p = this._MOT2002Support;
        const voltageBuffer = p.voltageBuffer;
        const index = p.voltageBufferIndex;
        let startAvgDiff = 0;
        let endAvgDiff = 0;
        let longTermAvg = 0;
        let triggered = false;
        if (p.voltageBufferReady) {
          longTermAvg = voltageBuffer.reduce((prev, curr) => prev + curr) / p.VOLTAGE_BUFFER_LEN;
          const longTermDiff = voltageBuffer.reduce((prev, curr) => prev + Math.abs(curr - longTermAvg), 0) / p.VOLTAGE_BUFFER_LEN;
          if (longTermDiff < 0.1) {
            p.motionSensorBaseline = longTermAvg;
          } else if (p.motionSensorBaseline === 1e+300) {
            return 2;
          }
          for (let i = 0; i < 5; i++) {
            startAvgDiff += Math.abs(voltageBuffer[(index + p.VOLTAGE_BUFFER_LEN - (i + 5)) % p.VOLTAGE_BUFFER_LEN] - p.motionSensorBaseline);
            endAvgDiff += Math.abs(voltageBuffer[(index + p.VOLTAGE_BUFFER_LEN - i) % p.VOLTAGE_BUFFER_LEN] - p.motionSensorBaseline);
          }
          startAvgDiff /= 5;
          endAvgDiff /= 5;
          if (p.motionSensorCountdown !== 0) {
            p.motionSensorCountdown--;
            triggered = true;
          }
          if (startAvgDiff > threshold && endAvgDiff > threshold) {
            p.motionSensorCountdown = 10;
            triggered = true;
          }
          return triggered;
        }
        return 2;
      }
    }

    /**
     * The Voltage Output class controls the variable DC voltage output on a Phidget board. This class provides settings for the output voltage as well as various safety controls.
     * @public
     */
    class VoltageOutputBase extends PhidgetChannel {
      /** @internal */
      data;
      constructor(ch) {
        super(ch);
        this._class = exports.ChannelClass.VOLTAGE_OUTPUT;
        this.name = "VoltageOutput";
        this.data = this._initData();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 56:
            this.data.enabled = bp.entries[0].v;
            this._FIREPropertyChange('Enabled', bp);
            break;
          case 146:
            break;
          case 147:
            break;
          case 86:
            this.data.voltage = bp.entries[0].v;
            this._FIREPropertyChange('Voltage', bp);
            break;
          case 87:
            this.data.voltageOutputRange = bp.entries[0].v;
            this._FIREPropertyChange('VoltageOutputRange', bp);
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.INVALID_PACKET, "Unsupported bridge packet: 0x" + bp.vpkt.toString(16));
        }
      }
      /** @internal */
      _initData() {
        return {
          enabled: 2,
          maxVoltage: 1e+300,
          minVoltage: 1e+300,
          voltage: 1e+300,
          voltageOutputRange: 2147483647,
          maxFailsafeTime: 4294967295,
          minFailsafeTime: 4294967295
        };
      }
      /** @internal */
      _initAfterOpen() {}
      /** @internal */
      async _setDefaults() {}
      /** @internal */
      _hasInitialState() {
        return true;
      }
      /** @internal */
      _fireInitialEvents() {}
      /**
       * Enable the output voltage by setting `enabled` to true.
       *
       * *   Disable the output by seting `enabled` to false to save power.
       * @throws `PhidgetError`
       */
      get enabled() {
        return this.getEnabled();
      }
      /**
       * The minimum value that `failsafeTime` can be set to when calling `enableFailsafe()`.
       * @throws `PhidgetError`
       */
      get minFailsafeTime() {
        return this.getMinFailsafeTime();
      }
      /**
       * The maximum value that `failsafeTime` can be set to when calling `enableFailsafe()`.
       * @throws `PhidgetError`
       */
      get maxFailsafeTime() {
        return this.getMaxFailsafeTime();
      }
      /**
       * The voltage value that the channel will output.
       *
       * *   The `voltage` value is bounded by `minVoltage` and `maxVoltage`.
       * *   The voltage value will not be output until `enabled` is set to true.
       * @throws `PhidgetError`
       */
      get voltage() {
        return this.getVoltage();
      }
      /**
       * The minimum value that `voltage` can be set to.
       * @throws `PhidgetError`
       */
      get minVoltage() {
        return this.getMinVoltage();
      }
      /**
       * The maximum value that `voltage` can be set to.
       * @throws `PhidgetError`
       */
      get maxVoltage() {
        return this.getMaxVoltage();
      }
      /**
       * Choose a `voltageOutputRange` that best suits your application.
       *
       * *   Changing the `voltageOutputRange` will also affect the `minVoltage` and `maxVoltage` values.
       * @throws `PhidgetError`
       */
      get voltageOutputRange() {
        return this.getVoltageOutputRange();
      }
      /**
       * Enable the output voltage by setting `enabled` to true.
       *
       * *   Disable the output by seting `enabled` to false to save power.
       * @returns The enabled value
       * @throws `PhidgetError`
       */
      getEnabled() {
        this._assertOpen();
        if (this.data.enabled === 2) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return !!this.data.enabled;
      }
      /**
       * Enable the output voltage by setting `enabled` to true.
       *
       * *   Disable the output by seting `enabled` to false to save power.
       * @throws `PhidgetError`
       * @param enabled - The enabled value
       */
      async setEnabled(enabled) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: enabled ? 1 : 0
        });
        await bp.send(this._ch, 56);
      }
      /**
       * Enables the **failsafe** feature for the channel, with the specified **failsafe time**.
       *
       * Enabling the failsafe feature starts a recurring **failsafe timer** for the channel. Once the failsafe is enabled, the timer must be reset within the specified time or the channel will enter a **failsafe state**. For Voltage Output channels, this will set the output voltage to 0V. The failsafe timer can be reset by using any of the following API calls:
       *
       * *   `setEnabled()`
       * *   `setVoltage()`
       * *   `setVoltageOutputRange()`
       * *   `resetFailsafe()`
       *
       * For more information about failsafe, visit our [Failsafe Guide](https://www.phidgets.com/docs/Failsafe_Guide).
       * @throws `PhidgetError`
       * @param failsafeTime - Failsafe timeout in milliseconds
       */
      async enableFailsafe(failsafeTime) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: failsafeTime
        });
        await bp.send(this._ch, 146);
      }
      /**
       * The minimum value that `failsafeTime` can be set to when calling `enableFailsafe()`.
       * @returns The failsafe time
       * @throws `PhidgetError`
       */
      getMinFailsafeTime() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 395:
          case 397:
          case 399:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.minFailsafeTime === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minFailsafeTime;
      }
      /**
       * The maximum value that `failsafeTime` can be set to when calling `enableFailsafe()`.
       * @returns The failsafe time
       * @throws `PhidgetError`
       */
      getMaxFailsafeTime() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 395:
          case 397:
          case 399:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.maxFailsafeTime === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxFailsafeTime;
      }
      /**
       * Resets the failsafe timer, if one has been set. See `enableFailsafe()` for details.
       *
       * This function will fail if no failsafe timer has been set for the channel.
       * @throws `PhidgetError`
       */
      async resetFailsafe() {
        this._assertOpen();
        const bp = new BridgePacket();
        await bp.send(this._ch, 147);
      }
      /**
       * The voltage value that the channel will output.
       *
       * *   The `voltage` value is bounded by `minVoltage` and `maxVoltage`.
       * *   The voltage value will not be output until `enabled` is set to true.
       * @returns The voltage value
       * @throws `PhidgetError`
       */
      getVoltage() {
        this._assertOpen();
        if (this.data.voltage === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.voltage;
      }
      /**
       * The voltage value that the channel will output.
       *
       * *   The `voltage` value is bounded by `minVoltage` and `maxVoltage`.
       * *   The voltage value will not be output until `enabled` is set to true.
       * @throws `PhidgetError`
       * @param voltage - The voltage value
       */
      async setVoltage(voltage) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: voltage
        });
        await bp.send(this._ch, 86);
      }
      /**
       * The minimum value that `voltage` can be set to.
       * @returns The voltage value
       * @throws `PhidgetError`
       */
      getMinVoltage() {
        this._assertOpen();
        if (this.data.minVoltage === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minVoltage;
      }
      /**
       * The maximum value that `voltage` can be set to.
       * @returns The voltage value
       * @throws `PhidgetError`
       */
      getMaxVoltage() {
        this._assertOpen();
        if (this.data.maxVoltage === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxVoltage;
      }
      /**
       * Choose a `voltageOutputRange` that best suits your application.
       *
       * *   Changing the `voltageOutputRange` will also affect the `minVoltage` and `maxVoltage` values.
       * @returns The output range value
       * @throws `PhidgetError`
       */
      getVoltageOutputRange() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 394:
          case 395:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.voltageOutputRange === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.voltageOutputRange;
      }
      /**
       * Choose a `voltageOutputRange` that best suits your application.
       *
       * *   Changing the `voltageOutputRange` will also affect the `minVoltage` and `maxVoltage` values.
       * @throws `PhidgetError`
       * @param voltageOutputRange - The output range value
       */
      async setVoltageOutputRange(voltageOutputRange) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: voltageOutputRange
        });
        await bp.send(this._ch, 87);
      }
    }

    /** @public */
    class VoltageOutput extends VoltageOutputBase {
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 87:
            super._bridgeInput(bp);
            switch (this.data.voltageOutputRange) {
              case exports.VoltageOutputRange.VOLTS_10:
                this.data.minVoltage = -10;
                this.data.maxVoltage = 10;
                break;
              case exports.VoltageOutputRange.VOLTS_5:
                this.data.minVoltage = 0;
                this.data.maxVoltage = 5;
                break;
            }
            this._FIREPropertyChange('MinVoltage', bp);
            this._FIREPropertyChange('MaxVoltage', bp);
            break;
          default:
            super._bridgeInput(bp);
            break;
        }
      }
    }

    /**
     * The Voltage Ratio Input class is used for measuring the ratio between the voltage supplied to and the voltage returned from an attached sensor or device. This is useful for interfacing with ratiometric sensors or wheatstone bridge based sensors.
     *
     * For ratiometric sensors, this class supports conversion to sensor data with units specific to the Phidget sensor being used, to make reading these sensors easy.
     * @public
     */
    class VoltageRatioInputBase extends PhidgetChannel {
      /** @internal */
      data;
      onVoltageRatioChange = null;
      /** @internal */
      _gotVoltageRatioChangeErrorEvent;
      onSensorChange = null;
      /** @internal */
      _gotSensorChangeErrorEvent;
      constructor(ch) {
        super(ch);
        this._class = exports.ChannelClass.VOLTAGE_RATIO_INPUT;
        this.name = "VoltageRatioInput";
        this.data = this._initData();
      }
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 56:
            this.data.bridgeEnabled = bp.entries[0].v;
            this._FIREPropertyChange('BridgeEnabled', bp);
            break;
          case 45:
            this.data.bridgeGain = bp.entries[0].v;
            this._FIREPropertyChange('BridgeGain', bp);
            break;
          case 54:
            if (bp.entryCount > 1) this.data.dataInterval = bp.entries[1].v;else this.data.dataInterval = bp.entries[0].v;
            this._FIREPropertyChange('DataInterval', bp);
            this._FIREPropertyChange('DataRate', bp);
            break;
          case 79:
            this.data.sensorType = bp.entries[0].v;
            this._FIREPropertyChange('SensorType', bp);
            break;
          case 122:
            this.data.sensorValueChangeTrigger = bp.entries[0].v;
            this._FIREPropertyChange('SensorValueChangeTrigger', bp);
            break;
          case 46:
            this.data.voltageRatioChangeTrigger = bp.entries[0].v;
            this._FIREPropertyChange('VoltageRatioChangeTrigger', bp);
            break;
          case 115:
            {
              this.data.sensorValue = bp.entries[0].v;
              const sensorUnit = {
                unit: bp.entries["UnitInfo.unit"].v,
                name: bp.entries["UnitInfo.name"].v,
                symbol: bp.entries["UnitInfo.symbol"].v
              };
              this.data.sensorUnit = sensorUnit;
              if (this._isAttachedDone && this.onSensorChange) {
                try {
                  this.onSensorChange(this.data.sensorValue, this.data.sensorUnit);
                } catch (err) {
                  logEventException(err);
                }
              }
              break;
            }
          default:
            throw new PhidgetError(exports.ErrorCode.INVALID_PACKET, "Unsupported bridge packet: 0x" + bp.vpkt.toString(16));
        }
      }
      /** @internal */
      _initData() {
        return {
          bridgeEnabled: 2,
          bridgeGain: 2147483647,
          dataInterval: 1e+300,
          minDataInterval: 4294967295,
          maxDataInterval: 4294967295,
          minDataRate: 1e+300,
          maxDataRate: 1e+300,
          sensorType: 2147483647,
          sensorUnit: null,
          sensorValue: 1e+300,
          voltageRatio: 1e+300,
          minVoltageRatio: 1e+300,
          maxVoltageRatio: 1e+300,
          voltageRatioChangeTrigger: 1e+300,
          minVoltageRatioChangeTrigger: 1e+300,
          maxVoltageRatioChangeTrigger: 1e+300,
          sensorValueChangeTrigger: 1e+300
        };
      }
      /** @internal */
      _initAfterOpen() {}
      /** @internal */
      async _setDefaults() {}
      /** @internal */
      _hasInitialState() {
        return true;
      }
      /** @internal */
      _fireInitialEvents() {}
      /**
       * Enable power to the input and start collecting data by setting `bridgeEnabled` to true.
       * @throws `PhidgetError`
       */
      get bridgeEnabled() {
        return this.getBridgeEnabled();
      }
      /**
       * Choose a `bridgeGain` that best suits your application.
       *
       * *   For more information about the range and accuracy of each `bridgeGain` to decide which best suits your application, see your device's User Guide.
       * @throws `PhidgetError`
       */
      get bridgeGain() {
        return this.getBridgeGain();
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between events can also be affected by the change trigger.
       * @throws `PhidgetError`
       */
      get dataInterval() {
        return this.getDataInterval();
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get minDataInterval() {
        return this.getMinDataInterval();
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataInterval() {
        return this.getMaxDataInterval();
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       */
      get dataRate() {
        return this.getDataRate();
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get minDataRate() {
        return this.getMinDataRate();
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @throws `PhidgetError`
       */
      get maxDataRate() {
        return this.getMaxDataRate();
      }
      /**
       * We sell a variety of analog sensors that do not have their own API, they simply output a voltage that can be converted to a digital value using a specific formula. By matching the `sensorType` to your analog sensor, the correct formula will automatically be applied to data when you get the `sensorValue` or subscribe to the `SensorChange` event.
       *
       * *   The `SensorChange` event has its own change trigger associated with it: `sensorValueChangeTrigger`.
       * *   Any data from getting the `sensorValue` or subscribing to the `SensorChange` event will have a `sensorUnit` associated with it.
       *
       * **Note:** Unlike other properties such as `Phidget.deviceSerialNumber` or `Phidget.channel`, `sensorType` is set after the device is opened, not before.
       * @throws `PhidgetError`
       */
      get sensorType() {
        return this.getSensorType();
      }
      /**
       * The unit of measurement that applies to the sensor values of the `sensorType` that has been selected.
       *
       * *   Helps keep track of the type of information being calculated from the voltage ratio input.
       * @throws `PhidgetError`
       */
      get sensorUnit() {
        return this.getSensorUnit();
      }
      /**
       * The most recent sensor value that the channel has reported.
       *
       * *   Use `sensorUnit` to get the measurement units that are associated with the `sensorValue`
       * @throws `PhidgetError`
       */
      get sensorValue() {
        return this.getSensorValue();
      }
      /**
       * The channel will not issue a `SensorChange` event until the sensor value has changed by the amount specified by the `sensorValueChangeTrigger`.
       *
       * *   Setting the `sensorValueChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @throws `PhidgetError`
       */
      get sensorValueChangeTrigger() {
        return this.getSensorValueChangeTrigger();
      }
      /**
       * The most recent voltage ratio value that the channel has reported.
       *
       * *   This value will always be between `minVoltageRatio` and `maxVoltageRatio`.
       * @throws `PhidgetError`
       */
      get voltageRatio() {
        return this.getVoltageRatio();
      }
      /**
       * The minimum value the `VoltageRatioChange` event will report.
       * @throws `PhidgetError`
       */
      get minVoltageRatio() {
        return this.getMinVoltageRatio();
      }
      /**
       * The maximum value the `VoltageRatioChange` event will report.
       * @throws `PhidgetError`
       */
      get maxVoltageRatio() {
        return this.getMaxVoltageRatio();
      }
      /**
       * The channel will not issue a `VoltageRatioChange` event until the voltage ratio value has changed by the amount specified by the `voltageRatioChangeTrigger`.
       *
       * *   Setting the `voltageRatioChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @throws `PhidgetError`
       */
      get voltageRatioChangeTrigger() {
        return this.getVoltageRatioChangeTrigger();
      }
      /**
       * The minimum value that `voltageRatioChangeTrigger` can be set to.
       * @throws `PhidgetError`
       */
      get minVoltageRatioChangeTrigger() {
        return this.getMinVoltageRatioChangeTrigger();
      }
      /**
       * The maximum value that `voltageRatioChangeTrigger` can be set to.
       * @throws `PhidgetError`
       */
      get maxVoltageRatioChangeTrigger() {
        return this.getMaxVoltageRatioChangeTrigger();
      }
      /**
       * Enable power to the input and start collecting data by setting `bridgeEnabled` to true.
       * @returns The enabled value
       * @throws `PhidgetError`
       */
      getBridgeEnabled() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 109:
          case 110:
          case 111:
          case 244:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.bridgeEnabled === 2) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return !!this.data.bridgeEnabled;
      }
      /**
       * Enable power to the input and start collecting data by setting `bridgeEnabled` to true.
       * @throws `PhidgetError`
       * @param bridgeEnabled - The enabled value
       */
      async setBridgeEnabled(bridgeEnabled) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: bridgeEnabled ? 1 : 0
        });
        await bp.send(this._ch, 56);
      }
      /**
       * Choose a `bridgeGain` that best suits your application.
       *
       * *   For more information about the range and accuracy of each `bridgeGain` to decide which best suits your application, see your device's User Guide.
       * @returns The bridge gain value
       * @throws `PhidgetError`
       */
      getBridgeGain() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 109:
          case 110:
          case 111:
          case 244:
            break;
          default:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.bridgeGain === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.bridgeGain;
      }
      /**
       * Choose a `bridgeGain` that best suits your application.
       *
       * *   For more information about the range and accuracy of each `bridgeGain` to decide which best suits your application, see your device's User Guide.
       * @throws `PhidgetError`
       * @param bridgeGain - The bridge gain value
       */
      async setBridgeGain(bridgeGain) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: bridgeGain
        });
        await bp.send(this._ch, 45);
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between events can also be affected by the change trigger.
       * @returns The data interval for the channel
       * @throws `PhidgetError`
       */
      getDataInterval() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.dataInterval;
      }
      /**
       * The `dataInterval` is the time that must elapse before the channel will fire another event.
       *
       * *   The data interval is bounded by `minDataInterval` and `maxDataInterval`.
       * *   The timing between events can also be affected by the change trigger.
       * @throws `PhidgetError`
       * @param dataInterval - The data interval for the channel
       */
      async setDataInterval(dataInterval) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: dataInterval
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMinDataInterval() {
        this._assertOpen();
        if (this.data.minDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataInterval;
      }
      /**
       * The maximum value that `dataInterval` can be set to.
       * @returns The data interval value
       * @throws `PhidgetError`
       */
      getMaxDataInterval() {
        this._assertOpen();
        if (this.data.maxDataInterval === 4294967295) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @returns The data rate for the channel
       * @throws `PhidgetError`
       */
      getDataRate() {
        this._assertOpen();
        if (this.data.dataInterval === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return 1000.0 / this.data.dataInterval;
      }
      /**
       * The `dataRate` is the frequency of events from the device.
       *
       * *   The data rate is bounded by `minDataRate` and `maxDataRate`.
       * *   Changing `dataRate` will change the channel's `dataInterval` to a corresponding value, rounded to the nearest integer number of milliseconds.
       * *   The timing between events can also affected by the change trigger.
       * @throws `PhidgetError`
       * @param dataRate - The data rate for the channel
       */
      async setDataRate(dataRate) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "u",
          value: Math.round(1000.0 / dataRate)
        });
        bp.set({
          name: "1",
          type: "g",
          value: 1000.0 / dataRate
        });
        await bp.send(this._ch, 54);
      }
      /**
       * The minimum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMinDataRate() {
        this._assertOpen();
        if (this.data.minDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minDataRate;
      }
      /**
       * The maximum value that `dataRate` can be set to.
       * @returns The data rate value
       * @throws `PhidgetError`
       */
      getMaxDataRate() {
        this._assertOpen();
        if (this.data.maxDataRate === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxDataRate;
      }
      /**
       * We sell a variety of analog sensors that do not have their own API, they simply output a voltage that can be converted to a digital value using a specific formula. By matching the `sensorType` to your analog sensor, the correct formula will automatically be applied to data when you get the `sensorValue` or subscribe to the `SensorChange` event.
       *
       * *   The `SensorChange` event has its own change trigger associated with it: `sensorValueChangeTrigger`.
       * *   Any data from getting the `sensorValue` or subscribing to the `SensorChange` event will have a `sensorUnit` associated with it.
       *
       * **Note:** Unlike other properties such as `Phidget.deviceSerialNumber` or `Phidget.channel`, `sensorType` is set after the device is opened, not before.
       * @returns The sensor type value
       * @throws `PhidgetError`
       */
      getSensorType() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 109:
          case 110:
          case 111:
          case 244:
          case 322:
          case 341:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.sensorType === 2147483647) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.sensorType;
      }
      /**
       * We sell a variety of analog sensors that do not have their own API, they simply output a voltage that can be converted to a digital value using a specific formula. By matching the `sensorType` to your analog sensor, the correct formula will automatically be applied to data when you get the `sensorValue` or subscribe to the `SensorChange` event.
       *
       * *   The `SensorChange` event has its own change trigger associated with it: `sensorValueChangeTrigger`.
       * *   Any data from getting the `sensorValue` or subscribing to the `SensorChange` event will have a `sensorUnit` associated with it.
       *
       * **Note:** Unlike other properties such as `Phidget.deviceSerialNumber` or `Phidget.channel`, `sensorType` is set after the device is opened, not before.
       * @throws `PhidgetError`
       * @param sensorType - The sensor type value
       */
      async setSensorType(sensorType) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "d",
          value: sensorType
        });
        await bp.send(this._ch, 79);
      }
      /**
       * The unit of measurement that applies to the sensor values of the `sensorType` that has been selected.
       *
       * *   Helps keep track of the type of information being calculated from the voltage ratio input.
       * @returns The sensor unit information corresponding to the `sensorValue`.
       * @throws `PhidgetError`
       */
      getSensorUnit() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 109:
          case 110:
          case 111:
          case 244:
          case 322:
          case 341:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.sensorUnit === null) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.sensorUnit;
      }
      /**
       * The most recent sensor value that the channel has reported.
       *
       * *   Use `sensorUnit` to get the measurement units that are associated with the `sensorValue`
       * @returns The sensor value
       * @throws `PhidgetError`
       */
      getSensorValue() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 109:
          case 110:
          case 111:
          case 244:
          case 322:
          case 341:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.sensorValue === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.sensorValue;
      }
      /**
       * The channel will not issue a `SensorChange` event until the sensor value has changed by the amount specified by the `sensorValueChangeTrigger`.
       *
       * *   Setting the `sensorValueChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getSensorValueChangeTrigger() {
        this._assertOpen();
        switch (this._ch?.chDef.uid) {
          case 109:
          case 110:
          case 111:
          case 244:
          case 322:
          case 341:
            throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
        }
        if (this.data.sensorValueChangeTrigger === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.sensorValueChangeTrigger;
      }
      /**
       * The channel will not issue a `SensorChange` event until the sensor value has changed by the amount specified by the `sensorValueChangeTrigger`.
       *
       * *   Setting the `sensorValueChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @throws `PhidgetError`
       * @param sensorValueChangeTrigger - The change trigger value
       */
      async setSensorValueChangeTrigger(sensorValueChangeTrigger) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: sensorValueChangeTrigger
        });
        await bp.send(this._ch, 122);
      }
      /**
       * The most recent voltage ratio value that the channel has reported.
       *
       * *   This value will always be between `minVoltageRatio` and `maxVoltageRatio`.
       * @returns The voltage ratio value
       * @throws `PhidgetError`
       */
      getVoltageRatio() {
        this._assertOpen();
        if (this.data.voltageRatio === 1e+300 || Number.isNaN(this.data.voltageRatio)) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        if (this.data.voltageRatio > this.data.maxVoltageRatio) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE_HIGH);
        if (this.data.voltageRatio < this.data.minVoltageRatio) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE_LOW);
        return this.data.voltageRatio;
      }
      /**
       * The minimum value the `VoltageRatioChange` event will report.
       * @returns The voltage ratio value
       * @throws `PhidgetError`
       */
      getMinVoltageRatio() {
        this._assertOpen();
        if (this.data.minVoltageRatio === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minVoltageRatio;
      }
      /**
       * The maximum value the `VoltageRatioChange` event will report.
       * @returns The voltage ratio value
       * @throws `PhidgetError`
       */
      getMaxVoltageRatio() {
        this._assertOpen();
        if (this.data.maxVoltageRatio === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxVoltageRatio;
      }
      /**
       * The channel will not issue a `VoltageRatioChange` event until the voltage ratio value has changed by the amount specified by the `voltageRatioChangeTrigger`.
       *
       * *   Setting the `voltageRatioChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getVoltageRatioChangeTrigger() {
        this._assertOpen();
        if (this.data.voltageRatioChangeTrigger === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.voltageRatioChangeTrigger;
      }
      /**
       * The channel will not issue a `VoltageRatioChange` event until the voltage ratio value has changed by the amount specified by the `voltageRatioChangeTrigger`.
       *
       * *   Setting the `voltageRatioChangeTrigger` to 0 will result in the channel firing events every `dataInterval`. This is useful for applications that implement their own data filtering
       * @throws `PhidgetError`
       * @param voltageRatioChangeTrigger - The change trigger value
       */
      async setVoltageRatioChangeTrigger(voltageRatioChangeTrigger) {
        this._assertOpen();
        const bp = new BridgePacket();
        bp.set({
          name: "0",
          type: "g",
          value: voltageRatioChangeTrigger
        });
        await bp.send(this._ch, 46);
      }
      /**
       * The minimum value that `voltageRatioChangeTrigger` can be set to.
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getMinVoltageRatioChangeTrigger() {
        this._assertOpen();
        if (this.data.minVoltageRatioChangeTrigger === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.minVoltageRatioChangeTrigger;
      }
      /**
       * The maximum value that `voltageRatioChangeTrigger` can be set to.
       * @returns The change trigger value
       * @throws `PhidgetError`
       */
      getMaxVoltageRatioChangeTrigger() {
        this._assertOpen();
        if (this.data.maxVoltageRatioChangeTrigger === 1e+300) throw new PhidgetError(exports.ErrorCode.UNKNOWN_VALUE);
        return this.data.maxVoltageRatioChangeTrigger;
      }
    }

    /** @public */
    class VoltageRatioInput extends VoltageRatioInputBase {
      /** @internal */
      _bridgeInput(bp) {
        switch (bp.vpkt) {
          case 10:
            if (bp.entryCount > 1) this.data.dataInterval = bp.getNumber(1);else this.data.dataInterval = bp.getNumber(0);
            this._FIREPropertyChange('DataInterval');
            this._FIREPropertyChange('DataRate');
            break;
          case 27:
            this.data.minDataInterval = bp.getNumber(0);
            this._FIREPropertyChange('MinDataInterval');
            break;
          case 79:
            super._bridgeInput(bp);
            this._bangSensorVoltage();
            break;
          case 102:
            {
              this.data.voltageRatio = bp.getNumber('0');
              const sentSensorEvent = this._bangSensorVoltage(true);
              if (sentSensorEvent && this._ch.conn._isRemote) throw new PhidgetError(exports.ErrorCode.UNSUPPORTED);
              break;
            }
          case 45:
            super._bridgeInput(bp);
            if (this._ch?.chDef.uid === 111) {
              switch (this.data.bridgeGain) {
                case exports.BridgeGain.GAIN_1X:
                  this.data.maxVoltageRatio = 0.85;
                  this.data.minVoltageRatio = -0.85;
                  break;
                case exports.BridgeGain.GAIN_8X:
                  this.data.maxVoltageRatio = 1.0 / 8;
                  this.data.minVoltageRatio = -1 / 8;
                  break;
                case exports.BridgeGain.GAIN_16X:
                  this.data.maxVoltageRatio = 1.0 / 16;
                  this.data.minVoltageRatio = -1 / 16;
                  break;
                case exports.BridgeGain.GAIN_32X:
                  this.data.maxVoltageRatio = 1.0 / 32;
                  this.data.minVoltageRatio = -1 / 32;
                  break;
                case exports.BridgeGain.GAIN_64X:
                  this.data.maxVoltageRatio = 1.0 / 64;
                  this.data.minVoltageRatio = -1 / 64;
                  break;
                case exports.BridgeGain.GAIN_128X:
                  this.data.maxVoltageRatio = 1.0 / 128;
                  this.data.minVoltageRatio = -1 / 128;
                  break;
              }
              this._FIREPropertyChange('MinVoltageRatio', bp);
              this._FIREPropertyChange('MaxVoltageRatio', bp);
            }
            break;
          default:
            super._bridgeInput(bp);
            break;
        }
      }
      /** @internal */
      _errorHandler(code) {
        switch (code) {
          case exports.ErrorEventCode.SATURATION:
            this.data.voltageRatio = 1e+300;
            this.data.sensorValue = 1e+300;
            this._gotVoltageRatioChangeErrorEvent = true;
            break;
        }
      }
      /** @internal */
      _initAfterOpen() {
        super._initAfterOpen();
        if (this.data.sensorType === 2147483647) this.data.sensorType = exports.VoltageRatioSensorType.VOLTAGE_RATIO;
        this.data.sensorUnit = this._getVoltageRatioSensorUnit(this.data.sensorType);
        this.data.sensorValue = this._getVoltageRatioSensorValue(this.data.voltageRatio, this.data.sensorType);
      }
      /** @internal */
      _hasInitialState() {
        if (this.data.voltageRatio == 1e+300 && !this._gotVoltageRatioChangeErrorEvent) return false;
        return super._hasInitialState();
      }
      /** @internal */
      _fireInitialEvents() {
        if (this.data.sensorType != exports.VoltageRatioSensorType.VOLTAGE_RATIO) {
          if (this.data.sensorValue != 1e+300 && this.data.sensorUnit != null) if (this.onSensorChange) {
            try {
              this.onSensorChange(this.data.sensorValue, this.data.sensorUnit);
            } catch (err) {
              logEventException(err);
            }
          }
        } else {
          if (this.data.voltageRatio != 1e+300) if (this.onVoltageRatioChange) {
            try {
              this.onVoltageRatioChange(this.data.voltageRatio);
            } catch (err) {
              logEventException(err);
            }
          }
        }
        super._fireInitialEvents();
      }
      /** @internal */
      _bangSensorVoltage(includeVoltage = false) {
        let sensorValue;
        let unitInfo;
        let sentSensorEvent = false;
        const bp = new BridgePacket();
        if (this._ch.supportedBridgePacket(115) && this._ch.conn._isLocal && this.data.sensorType !== exports.VoltageRatioSensorType.VOLTAGE_RATIO) {
          sensorValue = this._getVoltageRatioSensorValue(this.data.voltageRatio, this.data.sensorType);
          if (!this._getSensorValueInRange(sensorValue, this.data.sensorType)) {
            this.data.sensorValue = 1e+300;
            if (this._isAttachedDone) {
              bp.set({
                name: '0',
                type: 'd',
                value: exports.ErrorEventCode.OUT_OF_RANGE
              });
              bp.set({
                name: '1',
                type: 's',
                value: 'Sensor value is ouside the valid range for this sensor.'
              });
              this._ch.sendErrorEvent(bp);
            }
          } else if (this.data.sensorValue === 1e+300 || Math.abs(sensorValue - this.data.sensorValue) >= this.data.sensorValueChangeTrigger) {
            this.data.sensorValue = sensorValue;
            if (this._isAttachedDone) {
              unitInfo = this._getVoltageRatioSensorUnit(this.data.sensorType);
              bp.set({
                name: '0',
                type: 'g',
                value: sensorValue
              });
              bp.set({
                name: 'UnitInfo.unit',
                type: 'g',
                value: unitInfo.unit
              });
              bp.set({
                name: 'UnitInfo.name',
                type: 's',
                value: unitInfo.name
              });
              bp.set({
                name: 'UnitInfo.symbol',
                type: 's',
                value: unitInfo.symbol
              });
              bp.sendToChannel(this._ch, 115);
            }
          }
          sentSensorEvent = true;
        } else if (includeVoltage) {
          this.data.sensorUnit = this._getVoltageRatioSensorUnit(this.data.sensorType);
          this.data.sensorValue = this._getVoltageRatioSensorValue(this.data.voltageRatio, this.data.sensorType);
          if (this._isAttachedDone && this.onVoltageRatioChange) {
            try {
              this.onVoltageRatioChange(this.data.voltageRatio);
            } catch (err) {
              logEventException(err);
            }
          }
        }
        return sentSensorEvent;
      }
      /** @internal */
      _getVoltageRatioSensorValue(voltageRatio, sensorType) {
        if (voltageRatio === 1e+300) {
          return 1e+300;
        }
        switch (sensorType) {
          case exports.VoltageRatioSensorType.PN_1101_SHARP2D120X:
          case exports.VoltageRatioSensorType.PN_3520:
            return RoundDouble(2.076 / (voltageRatio - 0.011), 2);
          case exports.VoltageRatioSensorType.PN_1101_SHARP2Y0A21:
          case exports.VoltageRatioSensorType.PN_3521:
            return RoundDouble(4.8 / (voltageRatio - 0.02), 2);
          case exports.VoltageRatioSensorType.PN_1101_SHARP2Y0A02:
          case exports.VoltageRatioSensorType.PN_3522:
            return RoundDouble(9.462 / (voltageRatio - 0.01692), 2);
          case exports.VoltageRatioSensorType.PN_1102:
            return voltageRatio < 0.4 ? 1 : 0;
          case exports.VoltageRatioSensorType.PN_1103:
            return voltageRatio < 0.1 ? 1 : 0;
          case exports.VoltageRatioSensorType.PN_1104:
            return RoundDouble(voltageRatio * 2 - 1, 5);
          case exports.VoltageRatioSensorType.PN_1105:
            return voltageRatio;
          case exports.VoltageRatioSensorType.PN_1106:
            return voltageRatio;
          case exports.VoltageRatioSensorType.PN_1107:
            return RoundDouble(voltageRatio * 190.6 - 40.2, 3);
          case exports.VoltageRatioSensorType.PN_1108:
            return RoundDouble((0.5 - voltageRatio) * 1000, 2);
          case exports.VoltageRatioSensorType.PN_1109:
            return voltageRatio;
          case exports.VoltageRatioSensorType.PN_1110:
            return voltageRatio < 0.5 ? 1 : 0;
          case exports.VoltageRatioSensorType.PN_1111:
            return RoundDouble(voltageRatio * 2 - 1, 5);
          case exports.VoltageRatioSensorType.PN_1112:
            return voltageRatio;
          case exports.VoltageRatioSensorType.PN_1113:
            return RoundDouble(voltageRatio * 2 - 1, 5);
          case exports.VoltageRatioSensorType.PN_1115:
            return RoundDouble(voltageRatio / 0.004 + 10, 3);
          case exports.VoltageRatioSensorType.PN_1116:
            return voltageRatio;
          case exports.VoltageRatioSensorType.PN_1118_AC:
            return RoundDouble(voltageRatio * 69.38, 3);
          case exports.VoltageRatioSensorType.PN_1118_DC:
            return RoundDouble(voltageRatio / 0.008 - 62.5, 3);
          case exports.VoltageRatioSensorType.PN_1119_AC:
            return RoundDouble(voltageRatio * 27.75, 4);
          case exports.VoltageRatioSensorType.PN_1119_DC:
            return RoundDouble(voltageRatio / 0.02 - 25, 4);
          case exports.VoltageRatioSensorType.PN_1120:
            return voltageRatio;
          case exports.VoltageRatioSensorType.PN_1121:
            return voltageRatio;
          case exports.VoltageRatioSensorType.PN_1122_AC:
            return RoundDouble(voltageRatio * 42.04, 3);
          case exports.VoltageRatioSensorType.PN_1122_DC:
            return RoundDouble(voltageRatio / 0.0132 - 37.8787, 3);
          case exports.VoltageRatioSensorType.PN_1124:
          case exports.VoltageRatioSensorType.PN_1125_TEMPERATURE:
            return RoundDouble(voltageRatio * 222.2 - 61.111, 3);
          case exports.VoltageRatioSensorType.PN_1125_HUMIDITY:
            return RoundDouble(voltageRatio * 190.6 - 40.2, 3);
          case exports.VoltageRatioSensorType.PN_1126:
            return RoundDouble(voltageRatio / 0.018 - 27.7777, 3);
          case exports.VoltageRatioSensorType.PN_1128:
            return RoundDouble(voltageRatio * 1296, 2);
          case exports.VoltageRatioSensorType.PN_1129:
            return voltageRatio > 0.5 ? 1 : 0;
          case exports.VoltageRatioSensorType.PN_1131:
            return RoundDouble(15.311 * Math.exp(voltageRatio * 5.199), 2);
          case exports.VoltageRatioSensorType.PN_1134:
            return voltageRatio;
          case exports.VoltageRatioSensorType.PN_1136:
            return RoundDouble(voltageRatio / 0.2 - 2.5, 4);
          case exports.VoltageRatioSensorType.PN_1137:
            return RoundDouble(voltageRatio / 0.057143 - 8.75, 4);
          case exports.VoltageRatioSensorType.PN_1138:
            return RoundDouble(voltageRatio / 0.018 - 2.222, 3);
          case exports.VoltageRatioSensorType.PN_1139:
            return RoundDouble(voltageRatio / 0.009 - 4.444, 3);
          case exports.VoltageRatioSensorType.PN_1140:
            return RoundDouble(voltageRatio / 0.002421 + 3.478, 2);
          case exports.VoltageRatioSensorType.PN_1141:
            return RoundDouble(voltageRatio / 0.0092 + 10.652, 2);
          case exports.VoltageRatioSensorType.PN_1146:
            return RoundDouble(1.3927 * Math.exp(1.967 * voltageRatio), 2);
          case exports.VoltageRatioSensorType.PN_3120:
            return RoundDouble(voltageRatio / 0.15432 - 0.647989, 4);
          case exports.VoltageRatioSensorType.PN_3121:
            return RoundDouble(voltageRatio / 0.0617295 - 1.619971, 4);
          case exports.VoltageRatioSensorType.PN_3122:
            return RoundDouble(voltageRatio / 0.0308647 - 3.239943, 3);
          case exports.VoltageRatioSensorType.PN_3123:
            return RoundDouble(voltageRatio / 0.0154324 - 6.479886, 3);
          case exports.VoltageRatioSensorType.PN_3130:
            return RoundDouble(voltageRatio * 190.6 - 40.2, 3);
          case exports.VoltageRatioSensorType.VOLTAGE_RATIO:
          default:
            return voltageRatio;
        }
      }
      /** @internal */
      _getSensorValueInRange(sensorValue, sensorType) {
        if (sensorValue === 1e+300) {
          return false;
        }
        switch (sensorType) {
          case exports.VoltageRatioSensorType.PN_1101_SHARP2D120X:
          case exports.VoltageRatioSensorType.PN_3520:
            return sensorValue >= 4.0 && sensorValue <= 30.0;
          case exports.VoltageRatioSensorType.PN_1101_SHARP2Y0A21:
          case exports.VoltageRatioSensorType.PN_3521:
            return sensorValue >= 10.0 && sensorValue <= 80.0;
          case exports.VoltageRatioSensorType.PN_1101_SHARP2Y0A02:
          case exports.VoltageRatioSensorType.PN_3522:
            return sensorValue >= 20.0 && sensorValue <= 150.0;
          case exports.VoltageRatioSensorType.PN_1102:
            return true;
          case exports.VoltageRatioSensorType.PN_1103:
            return true;
          case exports.VoltageRatioSensorType.PN_1104:
            return true;
          case exports.VoltageRatioSensorType.PN_1105:
            return true;
          case exports.VoltageRatioSensorType.PN_1106:
            return true;
          case exports.VoltageRatioSensorType.PN_1107:
            return sensorValue >= 0.0 && sensorValue <= 100.0;
          case exports.VoltageRatioSensorType.PN_1108:
            return sensorValue >= -500 && sensorValue <= 500.0;
          case exports.VoltageRatioSensorType.PN_1109:
            return true;
          case exports.VoltageRatioSensorType.PN_1110:
            return true;
          case exports.VoltageRatioSensorType.PN_1111:
            return true;
          case exports.VoltageRatioSensorType.PN_1112:
            return true;
          case exports.VoltageRatioSensorType.PN_1113:
            return sensorValue >= -1 && sensorValue <= 1.0;
          case exports.VoltageRatioSensorType.PN_1115:
            return sensorValue >= 20.0 && sensorValue <= 250.0;
          case exports.VoltageRatioSensorType.PN_1116:
            return true;
          case exports.VoltageRatioSensorType.PN_1118_AC:
            return sensorValue >= 0.0 && sensorValue <= 50.0;
          case exports.VoltageRatioSensorType.PN_1118_DC:
            return sensorValue >= -50 && sensorValue <= 50.0;
          case exports.VoltageRatioSensorType.PN_1119_AC:
            return sensorValue >= 0.0 && sensorValue <= 20.0;
          case exports.VoltageRatioSensorType.PN_1119_DC:
            return sensorValue >= -20 && sensorValue <= 20.0;
          case exports.VoltageRatioSensorType.PN_1120:
            return true;
          case exports.VoltageRatioSensorType.PN_1121:
            return true;
          case exports.VoltageRatioSensorType.PN_1122_AC:
            return sensorValue >= 0.0 && sensorValue <= 30.0;
          case exports.VoltageRatioSensorType.PN_1122_DC:
            return sensorValue >= -30 && sensorValue <= 30.0;
          case exports.VoltageRatioSensorType.PN_1124:
          case exports.VoltageRatioSensorType.PN_1125_TEMPERATURE:
            return sensorValue >= -50 && sensorValue <= 150.0;
          case exports.VoltageRatioSensorType.PN_1125_HUMIDITY:
            return sensorValue >= 0.0 && sensorValue <= 100.0;
          case exports.VoltageRatioSensorType.PN_1126:
            return sensorValue >= -25 && sensorValue <= 25.0;
          case exports.VoltageRatioSensorType.PN_1128:
            return sensorValue >= 15.24 && sensorValue <= 6500.0;
          case exports.VoltageRatioSensorType.PN_1129:
            return true;
          case exports.VoltageRatioSensorType.PN_1131:
            return sensorValue >= 0.0 && sensorValue <= 2000.0;
          case exports.VoltageRatioSensorType.PN_1134:
            return true;
          case exports.VoltageRatioSensorType.PN_1136:
            return sensorValue >= -2 && sensorValue <= 2.0;
          case exports.VoltageRatioSensorType.PN_1137:
            return sensorValue >= -7 && sensorValue <= 7.0;
          case exports.VoltageRatioSensorType.PN_1138:
            return sensorValue >= 0.0 && sensorValue <= 50.0;
          case exports.VoltageRatioSensorType.PN_1139:
            return sensorValue >= 0.0 && sensorValue <= 100.0;
          case exports.VoltageRatioSensorType.PN_1140:
            return sensorValue >= 20.0 && sensorValue <= 400.0;
          case exports.VoltageRatioSensorType.PN_1141:
            return sensorValue >= 15.0 && sensorValue <= 115.0;
          case exports.VoltageRatioSensorType.PN_1146:
            return sensorValue >= 1.5 && sensorValue <= 4.0;
          case exports.VoltageRatioSensorType.PN_3120:
            return sensorValue >= 0.0 && sensorValue <= 4.5;
          case exports.VoltageRatioSensorType.PN_3121:
            return sensorValue >= 0.0 && sensorValue <= 11.3;
          case exports.VoltageRatioSensorType.PN_3122:
            return sensorValue >= 0.0 && sensorValue <= 22.7;
          case exports.VoltageRatioSensorType.PN_3123:
            return sensorValue >= 0.0 && sensorValue <= 45.3;
          case exports.VoltageRatioSensorType.PN_3130:
            return sensorValue >= 0.0 && sensorValue <= 100.0;
          case exports.VoltageRatioSensorType.VOLTAGE_RATIO:
            return true;
          default:
            return true;
        }
      }
      /** @internal */
      _getVoltageRatioSensorUnit(sensorType) {
        switch (sensorType) {
          case exports.VoltageRatioSensorType.PN_1146:
            return Units[exports.Unit.MILLIMETER];
          case exports.VoltageRatioSensorType.PN_1101_SHARP2D120X:
          case exports.VoltageRatioSensorType.PN_1101_SHARP2Y0A21:
          case exports.VoltageRatioSensorType.PN_1101_SHARP2Y0A02:
          case exports.VoltageRatioSensorType.PN_1128:
          case exports.VoltageRatioSensorType.PN_3520:
          case exports.VoltageRatioSensorType.PN_3521:
          case exports.VoltageRatioSensorType.PN_3522:
            return Units[exports.Unit.CENTIMETER];
          case exports.VoltageRatioSensorType.PN_1102:
          case exports.VoltageRatioSensorType.PN_1103:
          case exports.VoltageRatioSensorType.PN_1110:
          case exports.VoltageRatioSensorType.PN_1129:
            return Units[exports.Unit.BOOLEAN];
          case exports.VoltageRatioSensorType.PN_1107:
          case exports.VoltageRatioSensorType.PN_1125_HUMIDITY:
          case exports.VoltageRatioSensorType.PN_3130:
            return Units[exports.Unit.PERCENT];
          case exports.VoltageRatioSensorType.PN_1108:
            return Units[exports.Unit.GAUSS];
          case exports.VoltageRatioSensorType.PN_1115:
          case exports.VoltageRatioSensorType.PN_1126:
          case exports.VoltageRatioSensorType.PN_1136:
          case exports.VoltageRatioSensorType.PN_1137:
          case exports.VoltageRatioSensorType.PN_1138:
          case exports.VoltageRatioSensorType.PN_1139:
          case exports.VoltageRatioSensorType.PN_1140:
          case exports.VoltageRatioSensorType.PN_1141:
            return Units[exports.Unit.KILOPASCAL];
          case exports.VoltageRatioSensorType.PN_1118_AC:
          case exports.VoltageRatioSensorType.PN_1119_AC:
          case exports.VoltageRatioSensorType.PN_1122_AC:
          case exports.VoltageRatioSensorType.PN_1118_DC:
          case exports.VoltageRatioSensorType.PN_1119_DC:
          case exports.VoltageRatioSensorType.PN_1122_DC:
            return Units[exports.Unit.AMPERE];
          case exports.VoltageRatioSensorType.PN_1124:
          case exports.VoltageRatioSensorType.PN_1125_TEMPERATURE:
            return Units[exports.Unit.DEGREE_CELCIUS];
          case exports.VoltageRatioSensorType.PN_1131:
            return Units[exports.Unit.GRAM];
          case exports.VoltageRatioSensorType.PN_3120:
          case exports.VoltageRatioSensorType.PN_3121:
          case exports.VoltageRatioSensorType.PN_3122:
          case exports.VoltageRatioSensorType.PN_3123:
            return Units[exports.Unit.KILOGRAM];
          case exports.VoltageRatioSensorType.VOLTAGE_RATIO:
          case exports.VoltageRatioSensorType.PN_1104:
          case exports.VoltageRatioSensorType.PN_1111:
          case exports.VoltageRatioSensorType.PN_1113:
          case exports.VoltageRatioSensorType.PN_1105:
          case exports.VoltageRatioSensorType.PN_1106:
          case exports.VoltageRatioSensorType.PN_1109:
          case exports.VoltageRatioSensorType.PN_1112:
          case exports.VoltageRatioSensorType.PN_1116:
          case exports.VoltageRatioSensorType.PN_1120:
          case exports.VoltageRatioSensorType.PN_1121:
          case exports.VoltageRatioSensorType.PN_1134:
          default:
            return Units[exports.Unit.NONE];
        }
      }
    }

    /** @internal */
    function CreatePhidgetChannel(ch) {
      switch (ch.class) {
        case exports.ChannelClass.ACCELEROMETER:
          return new Accelerometer(ch);
        case exports.ChannelClass.BLDC_MOTOR:
          return new BLDCMotor(ch);
        case exports.ChannelClass.CAPACITIVE_TOUCH:
          return new CapacitiveTouch(ch);
        case exports.ChannelClass.CURRENT_INPUT:
          return new CurrentInput(ch);
        case exports.ChannelClass.DATA_ADAPTER:
          return new DataAdapter(ch);
        case exports.ChannelClass.DC_MOTOR:
          return new DCMotor(ch);
        case exports.ChannelClass.DICTIONARY:
          return new Dictionary(ch);
        case exports.ChannelClass.DIGITAL_INPUT:
          return new DigitalInput(ch);
        case exports.ChannelClass.DIGITAL_OUTPUT:
          return new DigitalOutput(ch);
        case exports.ChannelClass.DISTANCE_SENSOR:
          return new DistanceSensor(ch);
        case exports.ChannelClass.ENCODER:
          return new Encoder(ch);
        case exports.ChannelClass.FIRMWARE_UPGRADE:
          return new FirmwareUpgrade(ch);
        case exports.ChannelClass.FREQUENCY_COUNTER:
          return new FrequencyCounter(ch);
        case exports.ChannelClass.GENERIC:
          return new Generic(ch);
        case exports.ChannelClass.GPS:
          return new GPS(ch);
        case exports.ChannelClass.GYROSCOPE:
          return new Gyroscope(ch);
        case exports.ChannelClass.HUB:
          return new Hub(ch);
        case exports.ChannelClass.HUMIDITY_SENSOR:
          return new HumiditySensor(ch);
        case exports.ChannelClass.IR:
          return new IR(ch);
        case exports.ChannelClass.LCD:
          return new LCD(ch);
        case exports.ChannelClass.LEDARRAY:
          return new LEDArray(ch);
        case exports.ChannelClass.LIGHT_SENSOR:
          return new LightSensor(ch);
        case exports.ChannelClass.MAGNETOMETER:
          return new Magnetometer(ch);
        case exports.ChannelClass.MOTOR_POSITION_CONTROLLER:
          return new MotorPositionController(ch);
        case exports.ChannelClass.MOTOR_VELOCITY_CONTROLLER:
          return new MotorVelocityController(ch);
        case exports.ChannelClass.PH_SENSOR:
          return new PHSensor(ch);
        case exports.ChannelClass.POWER_GUARD:
          return new PowerGuard(ch);
        case exports.ChannelClass.PRESSURE_SENSOR:
          return new PressureSensor(ch);
        case exports.ChannelClass.RC_SERVO:
          return new RCServo(ch);
        case exports.ChannelClass.RESISTANCE_INPUT:
          return new ResistanceInput(ch);
        case exports.ChannelClass.RFID:
          return new RFID(ch);
        case exports.ChannelClass.SOUND_SENSOR:
          return new SoundSensor(ch);
        case exports.ChannelClass.SPATIAL:
          return new Spatial(ch);
        case exports.ChannelClass.STEPPER:
          return new Stepper(ch);
        case exports.ChannelClass.TEMPERATURE_SENSOR:
          return new TemperatureSensor(ch);
        case exports.ChannelClass.VOLTAGE_INPUT:
          return new VoltageInput(ch);
        case exports.ChannelClass.VOLTAGE_OUTPUT:
          return new VoltageOutput(ch);
        case exports.ChannelClass.VOLTAGE_RATIO_INPUT:
          return new VoltageRatioInput(ch);
        default:
          throw new Error("Invalid Channel Class");
      }
    }

    /**
     * @public
     */
    class Manager {
      /** @internal */
      _isopen;
      onDeviceAttach = null;
      onDeviceDetach = null;
      onAttach = null;
      onDetach = null;
      /**
       * The Phidget Manager allows tracking of which Phidgets are available to be controlled from the current program.
       * This is useful for listing all available Phidgets so you can select which ones to use at runtime.
       *
       * You do not need to use a Phidget Manager if you know what Phidgets will be required for your application
       * in advance.
       *
       * Phidget channels that become available will each send an Attach event, and Phidgets that are removed
       * from the system will send corresponding Detach events. If you are using a Phidget Manager, your program
       * is responsible for keeping track of available Phidgets using these events.
       *
       * @param opts - Event callbacks can be specified via this object
       */
      constructor(opts) {
        this._isopen = false;
        if (typeof opts === 'object') {
          if ('onDeviceAttach' in opts && typeof opts.onDeviceAttach === 'function') this.onDeviceAttach = opts.onDeviceAttach;
          if ('onDeviceDetach' in opts && typeof opts.onDeviceDetach === 'function') this.onDeviceDetach = opts.onDeviceDetach;
          if ('onAttach' in opts && typeof opts.onAttach === 'function') this.onAttach = opts.onAttach;
          if ('onDetach' in opts && typeof opts.onDetach === 'function') this.onDetach = opts.onDetach;
        }
      }
      open() {
        if (this._isopen) return;
        Managers.push(this);
        for (const conn of Connections) {
          if (this.onDeviceAttach) {
            for (const d of conn._devices.values()) {
              const phid = new PhidgetDevice(d);
              try {
                this.onDeviceAttach(phid);
              } catch (err) {
                logEventException(err);
              }
            }
          }
          if (this.onAttach) {
            for (const ch of conn._channels.values()) {
              const phid = CreatePhidgetChannel(ch);
              try {
                this.onAttach(phid);
              } catch (err) {
                logEventException(err);
              }
            }
          }
        }
        this._isopen = true;
      }
      close() {
        this._isopen = false;
        if (_includesInstanceProperty(Managers).call(Managers, this)) Managers.splice(Managers.indexOf(this), 1);
      }
      /** @internal */
      _deviceAttach(dev) {
        if (this._isopen && this.onDeviceAttach) {
          const phdev = new PhidgetDevice(dev);
          try {
            this.onDeviceAttach(phdev);
          } catch (err) {
            logEventException(err);
          }
        }
      }
      /** @internal */
      _deviceDetach(dev) {
        if (this._isopen && this.onDeviceDetach) {
          const phdev = new PhidgetDevice(dev);
          try {
            this.onDeviceDetach(phdev);
          } catch (err) {
            logEventException(err);
          }
        }
      }
      /** @internal */
      _channelAttach(ch) {
        if (this._isopen && this.onAttach) {
          const phch = CreatePhidgetChannel(ch);
          try {
            this.onAttach(phch);
          } catch (err) {
            logEventException(err);
          }
        }
      }
      /** @internal */
      _channelDetach(ch) {
        if (this._isopen && this.onDetach) {
          const phch = CreatePhidgetChannel(ch);
          try {
            this.onDetach(phch);
          } catch (err) {
            logEventException(err);
          }
        }
      }
    }

    exports.Accelerometer = Accelerometer;
    exports.BLDCMotor = BLDCMotor;
    exports.CapacitiveTouch = CapacitiveTouch;
    exports.Connection = NetworkConnection;
    exports.CurrentInput = CurrentInput;
    exports.DCMotor = DCMotor;
    exports.DataAdapter = DataAdapter;
    exports.Dictionary = Dictionary;
    exports.DigitalInput = DigitalInput;
    exports.DigitalOutput = DigitalOutput;
    exports.DistanceSensor = DistanceSensor;
    exports.Encoder = Encoder;
    exports.FirmwareUpgrade = FirmwareUpgrade;
    exports.FrequencyCounter = FrequencyCounter;
    exports.GPS = GPS;
    exports.Generic = Generic;
    exports.Gyroscope = Gyroscope;
    exports.Hub = Hub;
    exports.HumiditySensor = HumiditySensor;
    exports.IR = IR;
    exports.JSLibraryVersion = JSLibraryVersion;
    exports.LCD = LCD;
    exports.LEDArray = LEDArray;
    exports.LibraryVersion = LibraryVersion;
    exports.LightSensor = LightSensor;
    exports.Log = Log;
    exports.Magnetometer = Magnetometer;
    exports.Manager = Manager;
    exports.MotorPositionController = MotorPositionController;
    exports.MotorVelocityController = MotorVelocityController;
    exports.NetworkConnection = NetworkConnection;
    exports.PHSensor = PHSensor;
    exports.Phidget = Phidget;
    exports.PhidgetConnection = PhidgetConnection;
    exports.PhidgetError = PhidgetError;
    exports.PowerGuard = PowerGuard;
    exports.PressureSensor = PressureSensor;
    exports.RCServo = RCServo;
    exports.RFID = RFID;
    exports.ResistanceInput = ResistanceInput;
    exports.SoundSensor = SoundSensor;
    exports.Spatial = Spatial;
    exports.Stepper = Stepper;
    exports.TemperatureSensor = TemperatureSensor;
    exports.VoltageInput = VoltageInput;
    exports.VoltageOutput = VoltageOutput;
    exports.VoltageRatioInput = VoltageRatioInput;

}));
//# sourceMappingURL=phidget22.net.js.map
