feetech-servo-ts
Version:
TypeScript SDK for Feetech servo motors using Web Serial API
2 lines (1 loc) • 21.9 kB
JavaScript
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const p={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},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}},k={scs_series:p,sts3215:p,sms_series:p},N={scs_series:4096,sts3215:4096,sms_series:4096},T={0:1e6,1:5e5,2:25e4,3:128e3,4:115200,5:57600,6:38400,7:19200},se={scs_series:T,sts3215:T,sms_series:T},re=["Goal_Position","Present_Position"],ne=["Goal_Position","Present_Position"];function h(r,e){const t=k[r];if(!t)throw new Error(`Unknown model: ${r}`);return t[e]}function ae(r,e){const t=new Set,s=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 v=(r=>(r.DEGREE="DEGREE",r.LINEAR="LINEAR",r))(v||{}),B=(r=>(r[r.NORMAL=0]="NORMAL",r[r.INVERTED=1]="INVERTED",r))(B||{}),y=(r=>(r.SCS_SERIES="scs_series",r.STS3215="sts3215",r.SMS_SERIES="sms_series",r))(y||{});const g={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 E=(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))(E||{}),u=(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 i extends Error{constructor(e,t,s){super(e),this.code=t,this.deviceId=s,this.name="ServoError"}}var c=(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 S=254,oe=253,_=[255,255],A=2,I=1,P=1,V=1,ie=1,b=1,L=A+I+P+V+b,C=1e6,R=1e3,ce=3,m=8,z=1,G=0,W=0,x=4095,de=2048,F=0,O=1023,he=.1,le=1;function w(r,e){return e<<8|r}function M(r){return r&255}function H(r){return r>>8&255}class ue{constructor(e={baudRate:C},t=R){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 i("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 i("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 i?e:new i(`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 i(`Failed to disconnect: ${e instanceof Error?e.message:"Unknown error"}`,c.CONNECTION_LOST)}}async write(e){if(!this.writer||!this.isOpen)throw new i("Port is not connected",c.CONNECTION_LOST);try{await this.writer.write(e)}catch(t){throw new i(`Write error: ${t instanceof Error?t.message:"Unknown error"}`,c.WRITE_ERROR)}}async read(e,t){if(!this.reader||!this.isOpen)throw new i("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 i(`Read timeout: expected ${e} bytes, got ${this.readBuffer.length}`,c.TIMEOUT);await new Promise(o=>setTimeout(o,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 i("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 U{createPacket(e,t,s){const n=(s==null?void 0:s.length)??0,a=L+n,o=new Uint8Array(a);o[0]=_[0],o[1]=_[1],o[2]=e,o[3]=n+2,o[4]=t,s&&n>0&&o.set(s,5);const d=this.calculateChecksum(o.slice(2,a-1));return o[a-1]=d,o}parsePacket(e){if(e.length<L)throw new i(`Packet too short: ${e.length} bytes`,c.INVALID_RESPONSE);if(e[0]!==_[0]||e[1]!==_[1])throw new i("Invalid packet header",c.INVALID_RESPONSE);const t=e[2],s=e[3],n=e[4],a=A+I+P+s;if(e.length<a)throw new i(`Incomplete packet: expected ${a} bytes, got ${e.length}`,c.INVALID_RESPONSE);const o=s-2,d=o>0?e.slice(5,5+o):new Uint8Array(0),l=e[a-1],f=this.calculateChecksum(e.slice(2,a-1));if(l!==f)throw new i(`Checksum mismatch: expected ${f}, got ${l}`,c.CHECKSUM_ERROR,t);return{id:t,instruction:0,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,E.PING)}createReadPacket(e,t,s){const n=new Uint8Array([t,s]);return this.createPacket(e,E.READ,n)}createWritePacket(e,t,s){const n=new Uint8Array(1+s.length);return n[0]=t,n.set(s,1),this.createPacket(e,E.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 o=2;for(const d of s)a[o]=d.id,a.set(d.values,o+1),o+=1+d.values.length;return this.createPacket(S,E.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(S,E.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 i(`Servo error (0x${e.error.toString(16)}): ${t.join(", ")}`,c.HARDWARE_ERROR,e.id)}isValidPacketStart(e){return e.length>=2&&e[0]===_[0]&&e[1]===_[1]}getPacketLength(e){return e.length<4?null:A+I+P+e[3]}}function $(r,e="scs_series"){const t=N[e]||4096;return Math.round(r/360*t)}function q(r,e="scs_series"){const t=N[e]||4096;return r/t*360}function Ee(r){return Math.round(r/114*O)}function _e(r){return r/O*114}function Y(r="scs_series"){var e;return((e=g[r])==null?void 0:e.maxPosition)??x}function K(r="scs_series"){var e;return((e=g[r])==null?void 0:e.minPosition)??W}function D(r,e="scs_series"){const t=K(e),s=Y(e);return Math.max(t,Math.min(s,r))}function Q(r){return Math.max(F,Math.min(O,r))}function j(r){if(r<0||r>253)throw new Error(`Invalid servo ID: ${r}. Must be between 0 and 253.`)}function we(r){return new Promise(e=>setTimeout(e,r))}function Re(r){let e=0;for(const t of r)e+=t;return~e&255}function fe(r,e){const t=Array.isArray(r)?r:[r],s=Array.isArray(e)?e:[e];return t.map((a,o)=>{const d=s[o]||s[0],l=N[d]||4096;return Math.round(a/180*(l/2))})}function X(r,e=2){return`0x${r.toString(16).padStart(e,"0").toUpperCase()}`}function pe(r){return Array.from(r).map(e=>X(e)).join(" ")}function Z(){return"serial"in navigator}async function Te(){if(!Z())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 J={0:1e6,1:5e5,2:25e4,3:128e3,4:115200,5:57600,6:38400,7:19200};function ee(r){for(const[e,t]of Object.entries(J))if(t===r)return Number(e);throw new Error(`Unsupported baud rate ${r}`)}function Ae(r){return J[r]??0}const Ie=Object.freeze(Object.defineProperty({__proto__:null,bytesToHexString:pe,calculateChecksum:Re,clampPosition:D,clampSpeed:Q,convertDegreesToSteps:fe,degreesToPosition:$,formatHex:X,getActualBaudRate:Ae,getBaudRateValue:ee,getModelMaxPosition:Y,getModelMinPosition:K,isWebSerialSupported:Z,positionToDegrees:q,requestPort:Te,rpmToSpeed:Ee,sleep:we,speedToRpm:_e,validateServoId:j},Symbol.toStringTag,{value:"Module"}));class Pe{constructor(e,t=R){this.portHandler=e,this.timeout=t,this.model="scs_series",this.packetHandler=new U}setModel(e){this.model=e}async sendAndReceive(e,t){for(await this.portHandler.flush(),await this.portHandler.write(e);;){await this.portHandler.waitForData(f=>f.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 i("Invalid packet length",c.INVALID_RESPONSE);const a=await this.portHandler.read(n-4),o=new Uint8Array(n);o.set(s),o.set(a,4);const d=this.packetHandler.parsePacket(o);if(d.id!==t)throw new i(`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=w(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 i(`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,m))}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 w(s[0],s[1])}async writeWord(e,t,s){const n=new Uint8Array([M(s),H(s)]);await this.writeData(e,t,n)}async readPosition(e){const t=h(this.model,"Present_Position");if(!t)throw new i("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 i("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 i("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 i("Torque_Enable not found in control table",c.INVALID_PARAMETER);await this.writeByte(e,s.address,t?z:G)}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 i("Required status entries not found in control table",c.INVALID_PARAMETER);const a=await this.readData(e,t.address,8);return{position:w(a[0],a[1]),speed:w(a[2],a[3]),load:w(a[4],a[5]),voltage:a[6]/10,temperature:a[7],moving:await this.readByte(e,n.address)===1,errorStatus:0}}async setID(e,t){if(t<0||t>253)throw new i("Invalid ID: must be between 0 and 253",c.INVALID_PARAMETER);const s=h(this.model,"ID");if(!s)throw new i("ID not found in control table",c.INVALID_PARAMETER);await this.writeByte(e,s.address,t)}async setBaudRate(e,t){let s;try{s=ee(t)}catch{throw new i(`Unsupported baud rate: ${t}`,c.INVALID_PARAMETER)}const n=h(this.model,"Baud_Rate");if(!n)throw new i("Baud_Rate not found in control table",c.INVALID_PARAMETER);await this.writeByte(e,n.address,s),await new Promise(a=>setTimeout(a,m))}async factoryReset(e){const t=this.packetHandler.createPacket(e,E.FACTORY_RESET);await this.sendAndReceive(t,e),await new Promise(s=>setTimeout(s,500))}async reboot(e){const t=this.packetHandler.createPacket(e,E.REBOOT);await this.sendAndReceive(t,e),await new Promise(s=>setTimeout(s,500))}}class me{constructor(e,t,s){this.portHandler=e,this.address=t,this.dataLength=s,this.dataMap=new Map,this.packetHandler=new U}addParam(e,t){if(t.length!==this.dataLength)throw new i(`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 i("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,m))}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 Ne{constructor(e,t,s,n=R){this.portHandler=e,this.address=t,this.dataLength=s,this.timeout=n,this.idList=new Set,this.dataMap=new Map,this.packetHandler=new U}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 i("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 i("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 o=this.packetHandler.parsePacket(a);if(o.id!==e)throw new i(`ID mismatch: expected ${e}, got ${o.id}`,c.INVALID_RESPONSE);return this.packetHandler.checkError(o),o}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 te{constructor(e={}){this.isConnected=!1,this.motors={};const{port:t={baudRate:C},motors:s={},defaultModel:n=y.SCS_SERIES,timeout:a=R}=e;this.portHandler=new ue(t,a),this.protocolHandler=new Pe(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=D(t,n),o=s!==void 0?Q(s):void 0;await this.protocolHandler.writePosition(e,a,o)}async setPositionInDegrees(e,t,s){const n=this.getModelByServoId(e),a=$(t,n);await this.writePosition(e,a,s)}async getPositionInDegrees(e){const t=await this.readPosition(e),s=this.getModelByServoId(e);return q(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(),j(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 me(this.portHandler,e,t)}createSyncRead(e,t){return this.ensureConnected(),new Ne(this.portHandler,e,t)}async syncWritePosition(e){this.ensureConnected();const t=h(this.defaultModel,"Goal_Position");if(!t)throw new i("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),o=D(n.position,a),d=new Uint8Array([M(o),H(o)]);s.addParam(n.id,d)}await s.txPacket()}async syncReadPosition(e){this.ensureConnected();const t=h(this.defaultModel,"Present_Position");if(!t)throw new i("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=new Map;for(const a of e){const o=s.getData(a);o&&o.length>=2&&n.set(a,w(o[0],o[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 i("Not connected to serial port",c.CONNECTION_LOST)}}exports.BROADCAST_ID=S;exports.CALIBRATION_REQUIRED=re;exports.CENTER_POSITION_VALUE=de;exports.CHECKSUM_LENGTH=b;exports.CONVERT_UINT32_TO_INT32_REQUIRED=ne;exports.CalibrationMode=v;exports.DEFAULT_BAUDRATE=C;exports.DEFAULT_RETRY_COUNT=ce;exports.DEFAULT_TIMEOUT=R;exports.DriveMode=B;exports.ERROR_LENGTH=ie;exports.ErrorBit=u;exports.ErrorCode=c;exports.FeetechServo=te;exports.HEADER=_;exports.HEADER_LENGTH=A;exports.ID_LENGTH=I;exports.INSTRUCTION_LENGTH=V;exports.Instruction=E;exports.LATENCY_TIMER=m;exports.LENGTH_LENGTH=P;exports.MAX_ID=oe;exports.MAX_POSITION_VALUE=x;exports.MAX_SPEED_VALUE=O;exports.MIN_PACKET_LENGTH=L;exports.MIN_POSITION_VALUE=W;exports.MIN_SPEED_VALUE=F;exports.MODEL_BAUDRATE_TABLE=se;exports.MODEL_CONFIGS=g;exports.MODEL_CONTROL_TABLE=k;exports.MODEL_RESOLUTION=N;exports.MotorModel=y;exports.SCS_SERIES_BAUDRATE_TABLE=T;exports.SCS_SERIES_CONTROL_TABLE=p;exports.ServoError=i;exports.TEMPERATURE_UNIT=le;exports.TORQUE_DISABLE=G;exports.TORQUE_ENABLE=z;exports.VOLTAGE_UNIT=he;exports.assertSameAddress=ae;exports.default=te;exports.getControlTableEntry=h;exports.getHighByte=H;exports.getLowByte=M;exports.helpers=Ie;exports.makeWord=w;