UNPKG

feetech-servo-ts

Version:

TypeScript SDK for Feetech servo motors using Web Serial API

901 lines (900 loc) 28.2 kB
const R = { // EEPROM Area Model: { address: 3, size: 2 }, ID: { address: 5, size: 1 }, Baud_Rate: { address: 6, size: 1 }, Return_Delay: { address: 7, size: 1 }, Response_Status_Level: { address: 8, size: 1 }, Min_Angle_Limit: { address: 9, size: 2 }, Max_Angle_Limit: { address: 11, size: 2 }, Max_Temperature_Limit: { address: 13, size: 1 }, Max_Voltage_Limit: { address: 14, size: 1 }, Min_Voltage_Limit: { address: 15, size: 1 }, Max_Torque_Limit: { address: 16, size: 2 }, Phase: { address: 18, size: 1 }, Unloading_Condition: { address: 19, size: 1 }, LED_Alarm_Condition: { address: 20, size: 1 }, P_Coefficient: { address: 21, size: 1 }, D_Coefficient: { address: 22, size: 1 }, I_Coefficient: { address: 23, size: 1 }, Minimum_Startup_Force: { address: 24, size: 2 }, CW_Dead_Zone: { address: 26, size: 1 }, CCW_Dead_Zone: { address: 27, size: 1 }, Protection_Current: { address: 28, size: 2 }, Angular_Resolution: { address: 30, size: 1 }, Offset: { address: 31, size: 2 }, Mode: { address: 33, size: 1 }, Protective_Torque: { address: 34, size: 1 }, Protection_Time: { address: 35, size: 1 }, Overload_Torque: { address: 36, size: 1 }, Speed_closed_loop_P_proportional_coefficient: { address: 37, size: 1 }, Over_Current_Protection_Time: { address: 38, size: 1 }, Velocity_closed_loop_I_integral_coefficient: { address: 39, size: 1 }, // RAM Area Torque_Enable: { address: 40, size: 1 }, Acceleration: { address: 41, size: 1 }, Goal_Position: { address: 42, size: 2 }, Goal_Time: { address: 44, size: 2 }, Goal_Speed: { address: 46, size: 2 }, Torque_Limit: { address: 48, size: 2 }, Lock: { address: 55, size: 1 }, Present_Position: { address: 56, size: 2 }, Present_Speed: { address: 58, size: 2 }, Present_Load: { address: 60, size: 2 }, Present_Voltage: { address: 62, size: 1 }, Present_Temperature: { address: 63, size: 1 }, Status: { address: 65, size: 1 }, Moving: { address: 66, size: 1 }, Present_Current: { address: 69, size: 2 }, Maximum_Acceleration: { address: 85, size: 2 } }, F = { scs_series: R, sts3215: R, sms_series: R }, N = { scs_series: 4096, sts3215: 4096, sms_series: 4096 }, A = { 0: 1e6, 1: 5e5, 2: 25e4, 3: 128e3, 4: 115200, 5: 57600, 6: 38400, 7: 19200 }, we = { scs_series: A, sts3215: A, sms_series: A }, Ee = ["Goal_Position", "Present_Position"], fe = ["Goal_Position", "Present_Position"]; function h(r, e) { const t = F[r]; if (!t) throw new Error(`Unknown model: ${r}`); return t[e]; } function _e(r, e) { const t = /* @__PURE__ */ new Set(), s = /* @__PURE__ */ new Set(); for (const n of r) { const a = h(n, e); if (!a) throw new Error(`Data name '${e}' not found for model '${n}'`); t.add(a.address), s.add(a.size); } if (t.size > 1) throw new Error( `Different models use different addresses for '${e}'. This is not supported.` ); if (s.size > 1) throw new Error( `Different models use different byte sizes for '${e}'. This is not supported.` ); } var q = /* @__PURE__ */ ((r) => (r.DEGREE = "DEGREE", r.LINEAR = "LINEAR", r))(q || {}), Y = /* @__PURE__ */ ((r) => (r[r.NORMAL = 0] = "NORMAL", r[r.INVERTED = 1] = "INVERTED", r))(Y || {}), L = /* @__PURE__ */ ((r) => (r.SCS_SERIES = "scs_series", r.STS3215 = "sts3215", r.SMS_SERIES = "sms_series", r))(L || {}); const C = { scs_series: { resolution: 4096, maxPosition: 4095, minPosition: 0, defaultBaudRate: 1e6 }, sts3215: { resolution: 4096, maxPosition: 4095, minPosition: 0, defaultBaudRate: 1e6 }, sms_series: { resolution: 4096, maxPosition: 4095, minPosition: 0, defaultBaudRate: 1e6 } }; var w = /* @__PURE__ */ ((r) => (r[r.PING = 1] = "PING", r[r.READ = 2] = "READ", r[r.WRITE = 3] = "WRITE", r[r.REG_WRITE = 4] = "REG_WRITE", r[r.ACTION = 5] = "ACTION", r[r.FACTORY_RESET = 6] = "FACTORY_RESET", r[r.REBOOT = 8] = "REBOOT", r[r.SYNC_WRITE = 131] = "SYNC_WRITE", r[r.SYNC_READ = 130] = "SYNC_READ", r))(w || {}), u = /* @__PURE__ */ ((r) => (r[r.VOLTAGE = 1] = "VOLTAGE", r[r.ANGLE = 2] = "ANGLE", r[r.OVERHEAT = 4] = "OVERHEAT", r[r.RANGE = 8] = "RANGE", r[r.CHECKSUM = 16] = "CHECKSUM", r[r.OVERLOAD = 32] = "OVERLOAD", r[r.INSTRUCTION = 64] = "INSTRUCTION", r))(u || {}); class o extends Error { constructor(e, t, s) { super(e), this.code = t, this.deviceId = s, this.name = "ServoError"; } } var c = /* @__PURE__ */ ((r) => (r.CONNECTION_FAILED = "CONNECTION_FAILED", r.CONNECTION_LOST = "CONNECTION_LOST", r.PORT_NOT_FOUND = "PORT_NOT_FOUND", r.PERMISSION_DENIED = "PERMISSION_DENIED", r.TIMEOUT = "TIMEOUT", r.CHECKSUM_ERROR = "CHECKSUM_ERROR", r.INVALID_RESPONSE = "INVALID_RESPONSE", r.DEVICE_NOT_FOUND = "DEVICE_NOT_FOUND", r.WRITE_ERROR = "WRITE_ERROR", r.READ_ERROR = "READ_ERROR", r.INVALID_PARAMETER = "INVALID_PARAMETER", r.HARDWARE_ERROR = "HARDWARE_ERROR", r))(c || {}); const g = 254, pe = 253, E = [255, 255], T = 2, P = 1, m = 1, K = 1, Re = 1, j = 1, D = T + P + m + K + j, M = 1e6, p = 1e3, Ae = 3, I = 8, Q = 1, X = 0, Z = 0, J = 4095, Te = 2048, ee = 0, S = 1023, Pe = 0.1, me = 1; function f(r, e) { return e << 8 | r; } function H(r) { return r & 255; } function k(r) { return r >> 8 & 255; } class te { constructor(e = { baudRate: M }, t = p) { this.options = e, this.timeout = t, this.port = null, this.reader = null, this.writer = null, this.readBuffer = new Uint8Array(0), this.isOpen = !1; } async connect() { try { if (!("serial" in navigator)) throw new o( "Web Serial API is not supported in this browser", c.CONNECTION_FAILED ); if (this.port = await navigator.serial.requestPort(), await this.port.open(this.options), !this.port.readable || !this.port.writable) throw new o( "Port is not readable or writable", c.CONNECTION_FAILED ); this.reader = this.port.readable.getReader(), this.writer = this.port.writable.getWriter(), this.isOpen = !0, this.startReading(); } catch (e) { throw e instanceof o ? e : new o( `Failed to connect: ${e instanceof Error ? e.message : "Unknown error"}`, c.CONNECTION_FAILED ); } } async disconnect() { try { this.isOpen = !1, this.reader && (await this.reader.cancel(), this.reader = null), this.writer && (await this.writer.close(), this.writer = null), this.port && (await this.port.close(), this.port = null), this.readBuffer = new Uint8Array(0); } catch (e) { throw new o( `Failed to disconnect: ${e instanceof Error ? e.message : "Unknown error"}`, c.CONNECTION_LOST ); } } async write(e) { if (!this.writer || !this.isOpen) throw new o("Port is not connected", c.CONNECTION_LOST); try { await this.writer.write(e); } catch (t) { throw new o( `Write error: ${t instanceof Error ? t.message : "Unknown error"}`, c.WRITE_ERROR ); } } async read(e, t) { if (!this.reader || !this.isOpen) throw new o("Port is not connected", c.CONNECTION_LOST); const s = t ?? this.timeout, n = Date.now(); for (; this.readBuffer.length < e; ) { if (Date.now() - n > s) throw new o( `Read timeout: expected ${e} bytes, got ${this.readBuffer.length}`, c.TIMEOUT ); await new Promise((i) => setTimeout(i, 1)); } const a = this.readBuffer.slice(0, e); return this.readBuffer = this.readBuffer.slice(e), a; } async flush() { this.readBuffer = new Uint8Array(0); } isConnected() { return this.isOpen && this.port !== null; } async startReading() { if (this.reader) try { for (; this.isOpen; ) { const { value: e, done: t } = await this.reader.read(); if (t) break; e && this.appendToBuffer(e); } } catch (e) { this.isOpen && console.error("Read error:", e); } } appendToBuffer(e) { const t = new Uint8Array(this.readBuffer.length + e.length); t.set(this.readBuffer), t.set(e, this.readBuffer.length), this.readBuffer = t; } async waitForData(e, t) { const s = t ?? this.timeout, n = Date.now(); for (; !e(this.readBuffer); ) { if (Date.now() - n > s) throw new o("Wait for data timeout", c.TIMEOUT); await new Promise((a) => setTimeout(a, 1)); } } getBufferLength() { return this.readBuffer.length; } peekBuffer(e) { return this.readBuffer.slice(0, Math.min(e, this.readBuffer.length)); } } class O { createPacket(e, t, s) { const n = (s == null ? void 0 : s.length) ?? 0, a = D + n, i = new Uint8Array(a); i[0] = E[0], i[1] = E[1], i[2] = e, i[3] = n + 2, i[4] = t, s && n > 0 && i.set(s, 5); const d = this.calculateChecksum(i.slice(2, a - 1)); return i[a - 1] = d, i; } parsePacket(e) { if (e.length < D) throw new o( `Packet too short: ${e.length} bytes`, c.INVALID_RESPONSE ); if (e[0] !== E[0] || e[1] !== E[1]) throw new o( "Invalid packet header", c.INVALID_RESPONSE ); const t = e[2], s = e[3], n = e[4], a = T + P + m + s; if (e.length < a) throw new o( `Incomplete packet: expected ${a} bytes, got ${e.length}`, c.INVALID_RESPONSE ); const i = s - 2, d = i > 0 ? e.slice(5, 5 + i) : new Uint8Array(0), l = e[a - 1], _ = this.calculateChecksum( e.slice(2, a - 1) ); if (l !== _) throw new o( `Checksum mismatch: expected ${_}, got ${l}`, c.CHECKSUM_ERROR, t ); return { id: t, instruction: 0, // Response packets don't have instruction parameters: d, length: s, error: n, checksum: l }; } calculateChecksum(e) { let t = 0; for (const s of e) t += s; return ~t & 255; } createPingPacket(e) { return this.createPacket(e, w.PING); } createReadPacket(e, t, s) { const n = new Uint8Array([t, s]); return this.createPacket(e, w.READ, n); } createWritePacket(e, t, s) { const n = new Uint8Array(1 + s.length); return n[0] = t, n.set(s, 1), this.createPacket(e, w.WRITE, n); } createSyncWritePacket(e, t, s) { let n = 0; for (const d of s) n += 1 + d.values.length; const a = new Uint8Array(2 + n); a[0] = e, a[1] = t; let i = 2; for (const d of s) a[i] = d.id, a.set(d.values, i + 1), i += 1 + d.values.length; return this.createPacket(g, w.SYNC_WRITE, a); } createSyncReadPacket(e, t, s) { const n = new Uint8Array(2 + s.length); return n[0] = e, n[1] = t, n.set(s, 2), this.createPacket(g, w.SYNC_READ, n); } checkError(e) { if (e.error === 0) return; const t = []; if (e.error & u.VOLTAGE && t.push("Input voltage error"), e.error & u.ANGLE && t.push("Angle limit error"), e.error & u.OVERHEAT && t.push("Overheat error"), e.error & u.RANGE && t.push("Out of range error"), e.error & u.CHECKSUM && t.push("Checksum error"), e.error & u.OVERLOAD && t.push("Overload error"), e.error & u.INSTRUCTION && t.push("Invalid instruction error"), t.length > 0) throw new o( `Servo error (0x${e.error.toString(16)}): ${t.join(", ")}`, c.HARDWARE_ERROR, e.id ); } isValidPacketStart(e) { return e.length >= 2 && e[0] === E[0] && e[1] === E[1]; } getPacketLength(e) { return e.length < 4 ? null : T + P + m + e[3]; } } function U(r, e = "scs_series") { const t = N[e] || 4096; return Math.round(r / 360 * t); } function v(r, e = "scs_series") { const t = N[e] || 4096; return r / t * 360; } function se(r) { return Math.round(r / 114 * S); } function re(r) { return r / S * 114; } function z(r = "scs_series") { var e; return ((e = C[r]) == null ? void 0 : e.maxPosition) ?? J; } function b(r = "scs_series") { var e; return ((e = C[r]) == null ? void 0 : e.minPosition) ?? Z; } function y(r, e = "scs_series") { const t = b(e), s = z(e); return Math.max(t, Math.min(s, r)); } function B(r) { return Math.max(ee, Math.min(S, r)); } function V(r) { if (r < 0 || r > 253) throw new Error(`Invalid servo ID: ${r}. Must be between 0 and 253.`); } function ne(r) { return new Promise((e) => setTimeout(e, r)); } function ae(r) { let e = 0; for (const t of r) e += t; return ~e & 255; } function ie(r, e) { const t = Array.isArray(r) ? r : [r], s = Array.isArray(e) ? e : [e]; return t.map((a, i) => { const d = s[i] || s[0], l = N[d] || 4096; return Math.round(a / 180 * (l / 2)); }); } function W(r, e = 2) { return `0x${r.toString(16).padStart(e, "0").toUpperCase()}`; } function oe(r) { return Array.from(r).map((e) => W(e)).join(" "); } function G() { return "serial" in navigator; } async function ce() { if (!G()) throw new Error("Web Serial API is not supported in this browser"); try { return await navigator.serial.requestPort(); } catch (r) { if (r instanceof Error && r.name === "NotFoundError") return null; throw r; } } const x = { 0: 1e6, 1: 5e5, 2: 25e4, 3: 128e3, 4: 115200, 5: 57600, 6: 38400, 7: 19200 }; function $(r) { for (const [e, t] of Object.entries(x)) if (t === r) return Number(e); throw new Error(`Unsupported baud rate ${r}`); } function de(r) { return x[r] ?? 0; } const Ie = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({ __proto__: null, bytesToHexString: oe, calculateChecksum: ae, clampPosition: y, clampSpeed: B, convertDegreesToSteps: ie, degreesToPosition: U, formatHex: W, getActualBaudRate: de, getBaudRateValue: $, getModelMaxPosition: z, getModelMinPosition: b, isWebSerialSupported: G, positionToDegrees: v, requestPort: ce, rpmToSpeed: se, sleep: ne, speedToRpm: re, validateServoId: V }, Symbol.toStringTag, { value: "Module" })); class he { // Default model constructor(e, t = p) { this.portHandler = e, this.timeout = t, this.model = "scs_series", this.packetHandler = new O(); } setModel(e) { this.model = e; } async sendAndReceive(e, t) { for (await this.portHandler.flush(), await this.portHandler.write(e); ; ) { await this.portHandler.waitForData((_) => _.length >= 2, this.timeout); const l = this.portHandler.peekBuffer(2); if (l[0] === 255 && l[1] === 255) break; await this.portHandler.read(1); } const s = await this.portHandler.read(4), n = this.packetHandler.getPacketLength(s); if (n === null) throw new o("Invalid packet length", c.INVALID_RESPONSE); const a = await this.portHandler.read(n - 4), i = new Uint8Array(n); i.set(s), i.set(a, 4); const d = this.packetHandler.parsePacket(i); if (d.id !== t) throw new o( `ID mismatch: expected ${t}, got ${d.id}`, c.INVALID_RESPONSE ); return this.packetHandler.checkError(d), d; } async ping(e) { const t = this.packetHandler.createPingPacket(e); await this.sendAndReceive(t, e); let s = 0, n = 0; try { const a = await this.readData(e, 3, 2); s = f(a[0], a[1]), n = (await this.readData(e, 2, 1))[0]; } catch { } return { id: e, modelNumber: s, firmwareVersion: n }; } async readData(e, t, s) { const n = this.packetHandler.createReadPacket(e, t, s), a = await this.sendAndReceive(n, e); if (a.parameters.length < s) throw new o( `Invalid read response: expected ${s} bytes, got ${a.parameters.length}`, c.INVALID_RESPONSE, e ); return a.parameters.slice(0, s); } async writeData(e, t, s) { const n = this.packetHandler.createWritePacket(e, t, s); await this.sendAndReceive(n, e), await new Promise((a) => setTimeout(a, I)); } async readByte(e, t) { return (await this.readData(e, t, 1))[0]; } async writeByte(e, t, s) { const n = new Uint8Array([s & 255]); await this.writeData(e, t, n); } async readWord(e, t) { const s = await this.readData(e, t, 2); return f(s[0], s[1]); } async writeWord(e, t, s) { const n = new Uint8Array([H(s), k(s)]); await this.writeData(e, t, n); } async readPosition(e) { const t = h(this.model, "Present_Position"); if (!t) throw new o("Present_Position not found in control table", c.INVALID_PARAMETER); return await this.readWord(e, t.address); } async writePosition(e, t, s) { if (s !== void 0) { const a = h(this.model, "Goal_Speed"); if (!a) throw new o("Goal_Speed not found in control table", c.INVALID_PARAMETER); await this.writeWord(e, a.address, s); } const n = h(this.model, "Goal_Position"); if (!n) throw new o("Goal_Position not found in control table", c.INVALID_PARAMETER); await this.writeWord(e, n.address, t); } async setTorque(e, t) { const s = h(this.model, "Torque_Enable"); if (!s) throw new o("Torque_Enable not found in control table", c.INVALID_PARAMETER); await this.writeByte( e, s.address, t ? Q : X ); } async readStatus(e) { const t = h(this.model, "Present_Position"), s = h(this.model, "Present_Voltage"), n = h(this.model, "Moving"); if (!t || !s || !n) throw new o("Required status entries not found in control table", c.INVALID_PARAMETER); const a = await this.readData( e, t.address, 8 // Position(2) + Speed(2) + Load(2) + Voltage(1) + Temperature(1) ); return { position: f(a[0], a[1]), speed: f(a[2], a[3]), load: f(a[4], a[5]), voltage: a[6] / 10, // Convert to volts temperature: a[7], moving: await this.readByte(e, n.address) === 1, errorStatus: 0 // Will be set from last response error }; } async setID(e, t) { if (t < 0 || t > 253) throw new o( "Invalid ID: must be between 0 and 253", c.INVALID_PARAMETER ); const s = h(this.model, "ID"); if (!s) throw new o("ID not found in control table", c.INVALID_PARAMETER); await this.writeByte(e, s.address, t); } async setBaudRate(e, t) { let s; try { s = $(t); } catch { throw new o( `Unsupported baud rate: ${t}`, c.INVALID_PARAMETER ); } const n = h(this.model, "Baud_Rate"); if (!n) throw new o("Baud_Rate not found in control table", c.INVALID_PARAMETER); await this.writeByte(e, n.address, s), await new Promise((a) => setTimeout(a, I)); } async factoryReset(e) { const t = this.packetHandler.createPacket(e, w.FACTORY_RESET); await this.sendAndReceive(t, e), await new Promise((s) => setTimeout(s, 500)); } async reboot(e) { const t = this.packetHandler.createPacket(e, w.REBOOT); await this.sendAndReceive(t, e), await new Promise((s) => setTimeout(s, 500)); } } class le { constructor(e, t, s) { this.portHandler = e, this.address = t, this.dataLength = s, this.dataMap = /* @__PURE__ */ new Map(), this.packetHandler = new O(); } addParam(e, t) { if (t.length !== this.dataLength) throw new o( `Data length mismatch: expected ${this.dataLength}, got ${t.length}`, c.INVALID_PARAMETER, e ); this.dataMap.set(e, new Uint8Array(t)); } removeParam(e) { this.dataMap.delete(e); } clearParam() { this.dataMap.clear(); } async txPacket() { if (this.dataMap.size === 0) throw new o( "No parameters to send", c.INVALID_PARAMETER ); const e = []; for (const [s, n] of this.dataMap) e.push({ id: s, values: n }); const t = this.packetHandler.createSyncWritePacket( this.address, this.dataLength, e ); await this.portHandler.flush(), await this.portHandler.write(t), await new Promise((s) => setTimeout(s, I)); } getAddress() { return this.address; } getDataLength() { return this.dataLength; } getParamCount() { return this.dataMap.size; } hasParam(e) { return this.dataMap.has(e); } getParam(e) { const t = this.dataMap.get(e); return t ? new Uint8Array(t) : void 0; } } class ue { constructor(e, t, s, n = p) { this.portHandler = e, this.address = t, this.dataLength = s, this.timeout = n, this.idList = /* @__PURE__ */ new Set(), this.dataMap = /* @__PURE__ */ new Map(), this.packetHandler = new O(); } addParam(e) { this.idList.add(e); } removeParam(e) { this.idList.delete(e), this.dataMap.delete(e); } clearParam() { this.idList.clear(), this.dataMap.clear(); } async txRxPacket() { if (this.idList.size === 0) throw new o( "No parameters to read", c.INVALID_PARAMETER ); this.dataMap.clear(); const e = Array.from(this.idList), t = this.packetHandler.createSyncReadPacket( this.address, this.dataLength, e ); await this.portHandler.flush(), await this.portHandler.write(t); for (const s of e) try { const n = await this.readResponse(s); n.parameters.length >= this.dataLength && this.dataMap.set(s, n.parameters.slice(0, this.dataLength)); } catch (n) { console.error(`Failed to read from servo ${s}:`, n); } } async readResponse(e) { for (; ; ) { await this.portHandler.waitForData((l) => l.length >= 2, this.timeout); const d = this.portHandler.peekBuffer(2); if (d[0] === 255 && d[1] === 255) break; await this.portHandler.read(1); } const t = await this.portHandler.read(4), s = this.packetHandler.getPacketLength(t); if (s === null) throw new o("Invalid packet length", c.INVALID_RESPONSE); const n = await this.portHandler.read(s - 4), a = new Uint8Array(s); a.set(t), a.set(n, 4); const i = this.packetHandler.parsePacket(a); if (i.id !== e) throw new o( `ID mismatch: expected ${e}, got ${i.id}`, c.INVALID_RESPONSE ); return this.packetHandler.checkError(i), i; } isAvailable(e, t, s) { const n = this.dataMap.get(e); return !!n && n.length >= this.dataLength; } getData(e, t, s) { const n = this.dataMap.get(e); return n ? new Uint8Array(n) : void 0; } getAddress() { return this.address; } getDataLength() { return this.dataLength; } getParamCount() { return this.idList.size; } hasParam(e) { return this.idList.has(e); } } class ye { constructor(e = {}) { this.isConnected = !1, this.motors = {}; const { port: t = { baudRate: M }, motors: s = {}, defaultModel: n = L.SCS_SERIES, timeout: a = p } = e; this.portHandler = new te(t, a), this.protocolHandler = new he(this.portHandler, a), this.motors = s, this.defaultModel = n, this.protocolHandler.setModel(n); } getModelByServoId(e) { for (const t in this.motors) { const s = this.motors[t]; if (s.id === e) return s.model; } return this.defaultModel; } setMotors(e) { this.motors = e; } getMotorModel(e) { return this.motors[e] ? this.motors[e].model : this.defaultModel; } setDefaultModel(e) { this.defaultModel = e, this.protocolHandler.setModel(e); } async connect() { await this.portHandler.connect(), this.isConnected = !0; } async disconnect() { await this.portHandler.disconnect(), this.isConnected = !1; } getConnectionStatus() { return this.isConnected && this.portHandler.isConnected(); } async ping(e) { return this.ensureConnected(), await this.protocolHandler.ping(e); } async scan(e = 0, t = 253) { this.ensureConnected(); const s = []; for (let n = e; n <= t; n++) try { const a = await this.ping(n); s.push(a); } catch { } return s; } async readPosition(e) { return this.ensureConnected(), await this.protocolHandler.readPosition(e); } async writePosition(e, t, s) { this.ensureConnected(); const n = this.getModelByServoId(e), a = y(t, n), i = s !== void 0 ? B(s) : void 0; await this.protocolHandler.writePosition(e, a, i); } async setPositionInDegrees(e, t, s) { const n = this.getModelByServoId(e), a = U(t, n); await this.writePosition(e, a, s); } async getPositionInDegrees(e) { const t = await this.readPosition(e), s = this.getModelByServoId(e); return v(t, s); } async enableTorque(e) { this.ensureConnected(), await this.protocolHandler.setTorque(e, !0); } async disableTorque(e) { this.ensureConnected(), await this.protocolHandler.setTorque(e, !1); } async readStatus(e) { return this.ensureConnected(), await this.protocolHandler.readStatus(e); } async setID(e, t) { this.ensureConnected(), V(t), await this.protocolHandler.setID(e, t); } async setBaudRate(e, t) { this.ensureConnected(), await this.protocolHandler.setBaudRate(e, t); } async factoryReset(e) { this.ensureConnected(), await this.protocolHandler.factoryReset(e); } async reboot(e) { this.ensureConnected(), await this.protocolHandler.reboot(e); } createSyncWrite(e, t) { return this.ensureConnected(), new le(this.portHandler, e, t); } createSyncRead(e, t) { return this.ensureConnected(), new ue(this.portHandler, e, t); } async syncWritePosition(e) { this.ensureConnected(); const t = h(this.defaultModel, "Goal_Position"); if (!t) throw new o("Goal_Position not found in control table", c.INVALID_PARAMETER); const s = this.createSyncWrite(t.address, t.size); for (const n of e) { const a = this.getModelByServoId(n.id), i = y(n.position, a), d = new Uint8Array([ H(i), k(i) ]); s.addParam(n.id, d); } await s.txPacket(); } async syncReadPosition(e) { this.ensureConnected(); const t = h(this.defaultModel, "Present_Position"); if (!t) throw new o("Present_Position not found in control table", c.INVALID_PARAMETER); const s = this.createSyncRead(t.address, t.size); for (const a of e) s.addParam(a); await s.txRxPacket(); const n = /* @__PURE__ */ new Map(); for (const a of e) { const i = s.getData(a); i && i.length >= 2 && n.set(a, f(i[0], i[1])); } return n; } async readByte(e, t) { return this.ensureConnected(), await this.protocolHandler.readByte(e, t); } async writeByte(e, t, s) { this.ensureConnected(), await this.protocolHandler.writeByte(e, t, s); } async readWord(e, t) { return this.ensureConnected(), await this.protocolHandler.readWord(e, t); } async writeWord(e, t, s) { this.ensureConnected(), await this.protocolHandler.writeWord(e, t, s); } async readData(e, t, s) { return this.ensureConnected(), await this.protocolHandler.readData(e, t, s); } async writeData(e, t, s) { this.ensureConnected(), await this.protocolHandler.writeData(e, t, s); } ensureConnected() { if (!this.getConnectionStatus()) throw new o( "Not connected to serial port", c.CONNECTION_LOST ); } } export { g as BROADCAST_ID, Ee as CALIBRATION_REQUIRED, Te as CENTER_POSITION_VALUE, j as CHECKSUM_LENGTH, fe as CONVERT_UINT32_TO_INT32_REQUIRED, q as CalibrationMode, M as DEFAULT_BAUDRATE, Ae as DEFAULT_RETRY_COUNT, p as DEFAULT_TIMEOUT, Y as DriveMode, Re as ERROR_LENGTH, u as ErrorBit, c as ErrorCode, ye as FeetechServo, E as HEADER, T as HEADER_LENGTH, P as ID_LENGTH, K as INSTRUCTION_LENGTH, w as Instruction, I as LATENCY_TIMER, m as LENGTH_LENGTH, pe as MAX_ID, J as MAX_POSITION_VALUE, S as MAX_SPEED_VALUE, D as MIN_PACKET_LENGTH, Z as MIN_POSITION_VALUE, ee as MIN_SPEED_VALUE, we as MODEL_BAUDRATE_TABLE, C as MODEL_CONFIGS, F as MODEL_CONTROL_TABLE, N as MODEL_RESOLUTION, L as MotorModel, A as SCS_SERIES_BAUDRATE_TABLE, R as SCS_SERIES_CONTROL_TABLE, o as ServoError, me as TEMPERATURE_UNIT, X as TORQUE_DISABLE, Q as TORQUE_ENABLE, Pe as VOLTAGE_UNIT, _e as assertSameAddress, ye as default, h as getControlTableEntry, k as getHighByte, H as getLowByte, Ie as helpers, f as makeWord };