@ikalogic/at1000 0.5.2 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/build/at1000-Bav5xUM1.mjs +3 -0
  2. package/build/at1000-Bav5xUM1.mjs.map +1 -0
  3. package/build/at1000-DjoKZEha.cjs +3 -0
  4. package/build/at1000-DjoKZEha.cjs.map +1 -0
  5. package/build/browser.cjs +1 -1
  6. package/build/browser.cjs.map +1 -1
  7. package/build/browser.d.cts +3 -3
  8. package/build/browser.d.cts.map +1 -1
  9. package/build/browser.d.mts +3 -3
  10. package/build/browser.d.mts.map +1 -1
  11. package/build/browser.mjs +1 -1
  12. package/build/browser.mjs.map +1 -1
  13. package/build/{com-DN1l6xqC.d.cts → com-Bkkgrsep.d.cts} +177 -177
  14. package/build/{com-DN1l6xqC.d.cts.map → com-Bkkgrsep.d.cts.map} +1 -1
  15. package/build/{com-DN1l6xqC.d.mts → com-Bkkgrsep.d.mts} +177 -177
  16. package/build/{com-DN1l6xqC.d.mts.map → com-Bkkgrsep.d.mts.map} +1 -1
  17. package/build/com.cjs +1 -1
  18. package/build/com.d.cts +1 -1
  19. package/build/com.d.mts +1 -1
  20. package/build/{common-BSrNhbq_.cjs → common-BUohXSqz.cjs} +2 -2
  21. package/build/{common-BSrNhbq_.cjs.map → common-BUohXSqz.cjs.map} +1 -1
  22. package/build/{events-Cf7iAMZP.d.cts → events-8aTmwMUi.d.cts} +6 -6
  23. package/build/events-8aTmwMUi.d.cts.map +1 -0
  24. package/build/{events-Cf7iAMZP.d.mts → events-8aTmwMUi.d.mts} +6 -6
  25. package/build/events-8aTmwMUi.d.mts.map +1 -0
  26. package/build/events.cjs +1 -1
  27. package/build/events.d.cts +1 -1
  28. package/build/events.d.mts +1 -1
  29. package/build/events.mjs +1 -1
  30. package/build/gpio-5-tRkdTW.d.mts +712 -0
  31. package/build/gpio-5-tRkdTW.d.mts.map +1 -0
  32. package/build/gpio-D3QEeLKh.d.cts +712 -0
  33. package/build/gpio-D3QEeLKh.d.cts.map +1 -0
  34. package/build/gpio.cjs +1 -1
  35. package/build/gpio.cjs.map +1 -1
  36. package/build/gpio.d.cts +2 -2
  37. package/build/gpio.d.mts +2 -2
  38. package/build/gpio.mjs +1 -1
  39. package/build/gpio.mjs.map +1 -1
  40. package/build/{hmi-B-potLdl.d.cts → hmi-BEMiVKDF.d.cts} +2 -2
  41. package/build/hmi-BEMiVKDF.d.cts.map +1 -0
  42. package/build/{hmi-B-potLdl.d.mts → hmi-BEMiVKDF.d.mts} +2 -2
  43. package/build/hmi-BEMiVKDF.d.mts.map +1 -0
  44. package/build/hmi.cjs +1 -1
  45. package/build/hmi.d.cts +1 -1
  46. package/build/hmi.d.mts +1 -1
  47. package/build/{at1000-gm586Tc9.d.mts → host-BBjSKRqs.d.mts} +18 -16
  48. package/build/host-BBjSKRqs.d.mts.map +1 -0
  49. package/build/{at1000-tUTVczQa.d.cts → host-DlP73amZ.d.cts} +18 -16
  50. package/build/host-DlP73amZ.d.cts.map +1 -0
  51. package/build/management-DqBsC1HB.cjs +7 -0
  52. package/build/management-DqBsC1HB.cjs.map +1 -0
  53. package/build/management-StKcAkgo.mjs +7 -0
  54. package/build/management-StKcAkgo.mjs.map +1 -0
  55. package/build/management.cjs +1 -1
  56. package/build/management.d.cts +75 -70
  57. package/build/management.d.cts.map +1 -1
  58. package/build/management.d.mts +75 -70
  59. package/build/management.d.mts.map +1 -1
  60. package/build/management.mjs +1 -1
  61. package/build/node.cjs +1 -1
  62. package/build/node.cjs.map +1 -1
  63. package/build/node.d.cts +3 -3
  64. package/build/node.d.cts.map +1 -1
  65. package/build/node.d.mts +3 -3
  66. package/build/node.d.mts.map +1 -1
  67. package/build/node.mjs +1 -1
  68. package/build/node.mjs.map +1 -1
  69. package/build/package-DNfLRnEC.mjs +2 -0
  70. package/build/package-DNfLRnEC.mjs.map +1 -0
  71. package/build/{package-0hAwYBa1.cjs → package-iERj9NJ6.cjs} +2 -2
  72. package/build/package-iERj9NJ6.cjs.map +1 -0
  73. package/build/{power-B8QFbKdP.d.cts → power-B3oUS0wU.d.cts} +18 -18
  74. package/build/power-B3oUS0wU.d.cts.map +1 -0
  75. package/build/{power-BZmXOJyK.d.mts → power-D08VFff6.d.mts} +18 -18
  76. package/build/power-D08VFff6.d.mts.map +1 -0
  77. package/build/power.cjs +1 -1
  78. package/build/power.cjs.map +1 -1
  79. package/build/power.d.cts +1 -1
  80. package/build/power.d.mts +1 -1
  81. package/build/power.mjs.map +1 -1
  82. package/build/relays-TADiLsPk.d.cts.map +1 -1
  83. package/build/relays-TADiLsPk.d.mts.map +1 -1
  84. package/build/relays.cjs +1 -1
  85. package/build/{rolldown-runtime-CMqjfN_6.cjs → rolldown-runtime-BocRIvOZ.cjs} +1 -1
  86. package/build/session-qWW9mqWH.d.cts.map +1 -1
  87. package/build/session-qWW9mqWH.d.mts.map +1 -1
  88. package/build/session.cjs +1 -1
  89. package/build/session.mjs +1 -1
  90. package/package.json +12 -22
  91. package/build/at1000-DbIvMQUc.cjs +0 -8
  92. package/build/at1000-DbIvMQUc.cjs.map +0 -1
  93. package/build/at1000-Zs18VzlP.mjs +0 -8
  94. package/build/at1000-Zs18VzlP.mjs.map +0 -1
  95. package/build/at1000-gm586Tc9.d.mts.map +0 -1
  96. package/build/at1000-tUTVczQa.d.cts.map +0 -1
  97. package/build/events-Cf7iAMZP.d.cts.map +0 -1
  98. package/build/events-Cf7iAMZP.d.mts.map +0 -1
  99. package/build/gpio-CsxbjhA_.d.cts +0 -406
  100. package/build/gpio-CsxbjhA_.d.cts.map +0 -1
  101. package/build/gpio-Dk-s_yMc.d.mts +0 -406
  102. package/build/gpio-Dk-s_yMc.d.mts.map +0 -1
  103. package/build/hmi-B-potLdl.d.cts.map +0 -1
  104. package/build/hmi-B-potLdl.d.mts.map +0 -1
  105. package/build/package-0hAwYBa1.cjs.map +0 -1
  106. package/build/package-CU5MagIg.mjs +0 -2
  107. package/build/package-CU5MagIg.mjs.map +0 -1
  108. package/build/power-B8QFbKdP.d.cts.map +0 -1
  109. package/build/power-BZmXOJyK.d.mts.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gpio-D3QEeLKh.d.cts","names":[],"sources":["../src/api/gpio.ts"],"mappings":";;;;;cASa,0BAAwB,EAAA;;;;cAIxB,2BAAyB,EAAA;;;;;;;;cAQzB,2BAAyB,EAAA;;;;;;;;;;cAUzB,4BAA0B,EAAA;;;;;;;;;;;;cAY1B,wBAAsB,EAAA;;;;;;;KAOvB,2BAA2B,EAAE,mBAAmB;KAChD,4BAA4B,EAAE,mBAAmB;KACjD,4BAA4B,EAAE,mBAAmB;KACjD,6BAA6B,EAAE,mBAAmB;KAClD,yBAAyB,EAAE,mBAAmB;cAEpD,kCAAgC,KAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAC1B,mCAAmC,EAAE,mBACxC;cAEH,kCAAgC,KAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAC1B,mCAAmC,EAAE,mBACxC;cAEH,mCAAiC,KAAA,KAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAI3B,oCAAoC,EAAE,kBACzC;cAEH,+BAA6B,KAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KACvB,gCAAgC,EAAE,mBAAmB;cAEpD,cAAY,EAAA;;;cACZ,aAAW,EAAA;;;cAElB,mBAAiB,EAAA;;;KACX,oBAAoB,EAAE,mBAAmB;cAExC,WAAS,EAAA;;;KACV,YAAY,EAAE,mBAAmB;cAiBvC,eAAa,EAAA,aAAA,EAAA,0BAAA,EAAA,yBAAA,EAAA,yBAAA,EAAA,sCAAA,EAAA;cAMb,gBAAc,EAAA,aAAA,EAAA,0BAAA,EAAA;;;;cACd,iBAAe,EAAA,qBAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAgCf,gBAAc,EAAA;;;;;cAKd,cAAY,EAAA;;;;;;;;;;;cAOZ,gBAAc,EAAA;;;;;;;;;;;;;;KAER,sBAAsB,EAAE,mBAAmB;KAC3C,qBAAqB,EAAE,mBAAmB;;;;;;;;KAQ1C,mBAAmB,EAAE,mBAAmB;KAC/C,qBAAqB,EAAE,mBAAmB;KAC1C;KACA,mBACH,WAAW,4BAA4B,2BACvC,aAAa,eAAe;EACxB,IAAI;EAAI,MAAM;;KACf,iBAAiB;EAAQ;EAAc;EAAe,IAAI;;KAC1D,gBAAgB,MAAM,iBAAiB;EAAQ;;KAC/C,eAAe,MAAM,gBAAgB;EACxC;EACA;EACA;;KAEG,mBAAmB,MAAM,gBAAgB;EAC5C;EACA;EACA,SAAS;;KAEN,gBAAgB,MAAM,gBAAgB;EAAQ;;KAC9C,sBAAsB,IAAI,QAAQ,wBAAwB,eAAe,MAC1E,4BAA4B,mBAAmB,MAC/C,gBAAgB;KACf,eAAe,cAAc,mBAAmB,yBAAyB,UAAU,QACpF,sBAAsB,IAAI;KAEzB,sBACD,gEACA,8DACA;KACQ,0BAA0B,eAAe;KAChD,cAAc,qBAAqB,cAAc,QAAQ,eAAe,MAAM;KAC9E;EAAwB;EAAc;EAAe,SAAS;;;cAGtD,mBAAmB;;WACrB;WACA,SAAS;WACT,OAAO,cAAc;;EAI9B,YAAY,MAAM,oBAAoB,wBAAuB;EAY7D,IAAI,eAAe;EAInB,UAAU;;KA2EP,mBAAmB,WAAW,gBAAgB,iDACxB,UAAU;KAEhC,iBAAiB,MAAM,UAAU,gDAClC,yDACe;KAEd,kBAAkB,QAAQ,gDACZ,2CACf;KAEC,iBAAiB,OAAO,qBAAqB,uBAAuB,OAAO,QAC5E,sBAAsB,WAAW,OAAO,OAAO;KAE9C;WACM,SAAS;WACT;WACA,WAAW;WACX;;;KAGC,0BAA0B,EAAE,mBAAmB;;KAE/C,oBAAoB,EAAE,mBAAmB;KACzC;EACV;EACA;EACA,SAAS;;;KAGC;KACA;EAA4B;EAAkB;;;KAE9C;EACL;EAAa;;EAAmB;EAAa;KAChD;cAES,mBAAiB,EAAA,aAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;KAOlB,oBAAoB,EAAE,mBAAmB;;cAGxC;mBAGkB;UAFrB;EAER,YAA6B,OAAO,SAAS,MAAM;;;;EAOnD,SAAS;;;;;;EAST,QAAQ,aAAa;;;;;;EAiBrB,OAAO,aAAa;;;;;EAgBpB,QAAQ,QAAQ;;;;;;;;EAehB,WAAW,QAAQ;;;;;;EAanB,YAAY,aAAa,QAAQ;;;;;EAgBjC,aAAa,QAAQ;;;;;;;;;;EAarB,YAAY;;;cAMD;mBACkB;WAAgC;EAA7D,YAA6B,OAAO,SAAyB;;;;;;EAO7D,gBAAgB,QAAQ,mCAAmC,QAAQ;;;;;;EAgBnE,iBAAiB,QAAQ,oCAAoC,QAAQ;;;;;EAwB/D,QAAQ;;;;;;EASR,MAAM,0BAA0B;;;;;;EActC,qBAAqB,QAAQ,gCAAgC,QAAQ;;;cAa1D;mBACkB;WAAgC;EAA7D,YAA6B,OAAO,SAAyB;;;;;;EAO7D,mBAAmB,QAAQ;;;;;;EAa3B,iBAAiB,OAAO,oBAAoB,QAAQ;;;;;EAe9C,QAAQ;;;;;;EASR,MAAM,gBAAgB;;;;;;;;;;;;cAoBjB,aAAa,YAAY;mBAEjB;mBACA;mBACA;EAHnB,YACmB,OAAO,SACP,eACA,OAAO;;;;;;;;;;;;;;;;;EAmB1B,WACQ,+CACA,gBAAgB,iDAEtB,IAAI,MACJ,UAAU,UACT,aACD,OACA,2BAA2B,iBAAiB,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;EAoCvE,YAAY,yCACV,IAAI,MACJ,OAAO,6BAA6B,sBACnC,aAAa,OAAO,4BAA4B,kBAAkB;;;;;;;;;;;;;;;;;;;EA2BrE,aACE,YACA,SAAS,iCACR,aAAa,OAAO;;;;;;;;;;;;;;;;;;EAoCvB,WACE,YACA,OAAO,mBACP,UAAU,0BACT,aAAa,OAAO;;;;;;EAUvB,MAAM,mBAAmB,aAAa,OAAO;;;;;EAQ7C,QAAQ,aAAa,OAAO;;;;;EAQ5B,WAAW,aAAa,OAAO;;EAK/B,SAAS,qBACP,MAAM,SAAS,gCAAgC,mBAAmB,2BACjE,aAAa,iBAAiB,OAAO,MAAM;;;;;;;;;;;;EAuB9C,IAAI;IAAY;MAAqB,QAAQ,mBAAmB;UAkCxD;UAeA;UAUA"}
package/build/gpio.cjs CHANGED
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./rolldown-runtime-CMqjfN_6.cjs"),t=require("./common-BSrNhbq_.cjs");let n=require("valibot");n=e.t(n,1);const r=n.picklist([`release`,`hold`],`Invalid sync action`),i=n.object({mode:n.literal(`analog`),direction:n.literal(`input`)}),a=n.object({mode:n.literal(`analog`),direction:n.literal(`output`),value:n.optional(t.n)}),o=n.object({mode:n.literal(`digital`),direction:n.literal(`input`),vil:t.t,vih:t.t}),s=n.object({mode:n.literal(`digital`),direction:n.literal(`output`),value:t.r,vol:t.n,voh:t.n,vil:t.t,vih:t.t}),c=n.object({mode:n.literal(`digital`),direction:n.literal(`open_drain`),value:t.r,vil:t.t,vih:t.t});n.omit(a,[`direction`,`mode`]),n.omit(o,[`direction`,`mode`]);const l=n.partial(n.omit(s,[`direction`,`mode`]),[`vih`,`vil`]);n.omit(c,[`direction`,`mode`]);const u=n.object({value:t.r}),d=n.object({value:t.t}),f=n.object({action:r}),p=n.object({hold_state:n.picklist([`held`,`released`])}),m=n.union([s,c,o,a,i]);var h=class{fetch;count;constructor(e,t){this.fetch=e,this.count=t.capabilities.io.count}reset(){return this.fetch(`/gpio/reset`,{method:`POST`,parseResponse:()=>{}})}digital(e){if(e<0||e>=this.count)throw Error(`Invalid GPIO pin ${e} (RESOURCE_NOT_FOUND)\n Suggestion: Use a pin number between 0 and ${this.count-1}\n Path: /gpio/${e}`);return new g(this.fetch,e)}analog(e){if(e<0||e>=this.count)throw Error(`Invalid GPIO pin ${e} (RESOURCE_NOT_FOUND)\n Suggestion: Use a pin number between 0 and ${this.count-1}\n Path: /gpio/${e}`);return new _(this.fetch,e)}hold(){return this.fetch(`/gpio/sync`,{method:`POST`,body:{action:`hold`},schema:f})}release(){return this.fetch(`/gpio/sync`,{method:`POST`,body:{action:`release`},schema:f})}read_config(e){if(e<0||e>=this.count)throw Error(`Invalid GPIO pin ${e} (RESOURCE_NOT_FOUND)\n Suggestion: Use a pin number between 0 and ${this.count-1}\n Path: /gpio/${e}/config`);return this.fetch(`/gpio/${e}/config`,{schema:m})}read_sync(){return this.fetch(`/gpio/sync`,{schema:p})}},g=class{fetch;id;constructor(e,t){this.fetch=e,this.id=t}configure_input(e){return this.fetch(`/gpio/${this.id}/config`,{method:`PATCH`,body:n.parse(o,{...e,mode:`digital`,direction:`input`}),schema:o})}configure_output(e){e=n.parse(l,e);let t={mode:`digital`,direction:`output`,value:e.value,vol:e.vol,voh:e.voh,vil:e.vil??e.vol+(e.voh-e.vol)/4,vih:e.vih??e.voh-(e.voh-e.vol)/4};return this.fetch(`/gpio/${this.id}/config`,{method:`PATCH`,body:n.parse(s,t),schema:s})}async read(){return(await this.fetch(`/gpio/${this.id}/state`,{schema:u})).value}async write(e){return(await this.fetch(`/gpio/${this.id}/state`,{method:`PUT`,body:n.parse(u,{value:e}),schema:u})).value}configure_open_drain(e){return this.fetch(`/gpio/${this.id}/config`,{method:`PATCH`,body:n.parse(c,{...e,mode:`digital`,direction:`open_drain`}),schema:c})}},_=class{fetch;id;constructor(e,t){this.fetch=e,this.id=t}configure_input(){return this.fetch(`/gpio/${this.id}/config`,{method:`PATCH`,body:{mode:`analog`,direction:`input`},schema:i})}configure_output(e){return this.fetch(`/gpio/${this.id}/config`,{method:`PATCH`,body:n.parse(a,{value:e,mode:`analog`,direction:`output`}),schema:a})}async read(){return(await this.fetch(`/gpio/${this.id}/state`,{schema:d})).value}async write(e){return(await this.fetch(`/gpio/${this.id}/state`,{method:`PUT`,body:{value:e},schema:d})).value}};exports.AnalogIO=_,exports.DigitalIO=g,exports.GpioApi=h,exports.analogInputConfiguration=i,exports.analogOutputConfiguration=a,exports.analogState=d,exports.digitalInputConfiguration=o,exports.digitalOutputConfiguration=s,exports.digitalState=u,exports.gpioConfiguration=m,exports.openDrainConfiguration=c,exports.syncState=p;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./rolldown-runtime-BocRIvOZ.cjs"),t=require("./common-BUohXSqz.cjs");let n=require("valibot");n=e.t(n,1);const r=n.picklist([`release`,`hold`],`Invalid sync action`),i=n.object({mode:n.literal(`analog`),direction:n.literal(`input`)}),a=n.object({mode:n.literal(`analog`),direction:n.literal(`output`),value:n.optional(t.n)}),o=n.object({mode:n.literal(`digital`),direction:n.literal(`input`),vil:t.t,vih:t.t}),s=n.object({mode:n.literal(`digital`),direction:n.literal(`output`),value:t.r,vol:t.n,voh:t.n,vil:t.t,vih:t.t}),c=n.object({mode:n.literal(`digital`),direction:n.literal(`open_drain`),value:t.r,vil:t.t,vih:t.t});n.omit(a,[`direction`,`mode`]),n.omit(o,[`direction`,`mode`]);const l=n.partial(n.omit(s,[`direction`,`mode`]),[`vih`,`vil`]);n.omit(c,[`direction`,`mode`]);const u=n.object({value:t.r}),d=n.object({value:t.t}),f=n.object({action:r}),p=n.object({hold_state:n.picklist([`held`,`released`])}),m=n.picklist([`read`,`write`,`wait_voltage`,`wait_level`,`delay`,`hold`,`release`]),h=n.pipe(n.number(),n.finite(),n.minValue(Number.MIN_VALUE)),g=n.pipe(n.number(),n.integer(),n.minValue(0),n.maxValue(31)),_=n.union([g,n.pipe(n.array(g),n.minLength(1))]),v=n.union([n.boolean(),t.n]),y=n.union([v,n.pipe(n.array(v),n.minLength(1))]),b=n.pipe(n.number(),n.integer(),n.minValue(1)),x=n.object({min:t.t,max:t.t}),S=n.picklist([`low`,`high`],`Invalid level`),C=n.union([n.boolean(),x]),w=n.variant(`op`,[n.object({op:n.literal(`read`),io:_,repeat:n.optional(b),delay:n.optional(h),expect:n.optional(C)}),n.object({op:n.literal(`write`),io:_,value:y}),n.object({op:n.literal(`wait_voltage`),io:g,min:n.optional(t.t),max:n.optional(t.t),timeout:n.optional(h),stable_for:n.optional(h)}),n.object({op:n.literal(`wait_level`),io:g,level:S,timeout:n.optional(h),stable_for:n.optional(h)}),n.object({op:n.literal(`delay`),duration:h}),n.object({op:n.literal(`hold`)}),n.object({op:n.literal(`release`)})]),T=n.object({timeout:h,commands:n.pipe(n.array(w),n.minLength(1),n.maxLength(65536))}),E=n.object({io:n.number(),value:n.union([n.boolean(),n.number()]),elapsed:n.number()}),D=n.object({op:m,io:n.optional(n.union([n.number(),n.array(n.number())])),value:n.optional(n.union([n.boolean(),n.number()])),samples:n.optional(n.array(E)),elapsed:n.number()}),O=n.object({elapsed:n.number(),results:n.array(D)});var k=class{elapsed;results;named;#e;constructor(e,t=[]){this.elapsed=e.elapsed,this.results=e.results;let n=Object.create(null);for(let r of t){let t=M(r,e.results[r.index]);n[r.name]=t}this.named=Object.freeze(n),this.#e=n}get(e){return this.#e[e]}toJSON(){return{elapsed:this.elapsed,results:this.results}}};const A=e=>{switch(e.op){case`read`:return Array.isArray(e.io)||(e.repeat??1)>1?`collection`:`scalar`;case`write`:return Array.isArray(e.io)&&e.io.length>1?`collection`:`scalar`;case`wait_voltage`:case`wait_level`:return`scalar`;default:return`control`}},j=(e,t)=>e.results.length===t.length&&e.results.every((e,n)=>{let r=t[n];if(e.op!==r.op)return!1;let i=`io`in r?r.io:void 0;if(Array.isArray(i)){if(!Array.isArray(e.io)||i.length!==e.io.length||!i.every((t,n)=>t===e.io[n]))return!1}else if(e.io!==i)return!1;let a=A(r);if(a===`control`)return e.value===void 0&&e.samples===void 0;if(a===`scalar`)return e.samples===void 0&&e.value!==void 0;let o=Array.isArray(i)?i:[i],s=o.length*(r.op===`read`?r.repeat??1:1);if(r.op===`read`&&s===1&&e.value!==void 0&&e.samples===void 0)return!0;if(e.value!==void 0)return!1;let c=e.samples??[];return c.length===s&&c.every((e,t)=>e.io===o[t%o.length])}),M=({name:e,index:t,command:n},r)=>{let i={name:e,index:t,op:n.op,elapsed:r.elapsed};switch(A(n)){case`scalar`:return{...i,kind:`scalar`,io:r.io,value:r.value};case`collection`:return{...i,kind:`collection`,io:r.io,samples:r.samples??[{io:r.io[0],value:r.value,elapsed:r.elapsed}]};default:return{...i,kind:`control`}}},N=n.union([s,c,o,a,i]);var P=class{fetch;count;constructor(e,t){this.fetch=e,this.count=t.capabilities.io.count}reset(){return this.fetch(`/gpio/reset`,{method:`POST`,parseResponse:()=>{}})}digital(e){if(e<0||e>=this.count)throw Error(`Invalid GPIO pin ${e} (RESOURCE_NOT_FOUND)\n Suggestion: Use a pin number between 0 and ${this.count-1}\n Path: /gpio/${e}`);return new F(this.fetch,e)}analog(e){if(e<0||e>=this.count)throw Error(`Invalid GPIO pin ${e} (RESOURCE_NOT_FOUND)\n Suggestion: Use a pin number between 0 and ${this.count-1}\n Path: /gpio/${e}`);return new I(this.fetch,e)}hold(){return this.fetch(`/gpio/sync`,{method:`POST`,body:{action:`hold`},schema:f})}release(){return this.fetch(`/gpio/sync`,{method:`POST`,body:{action:`release`},schema:f})}read_config(e){if(e<0||e>=this.count)throw Error(`Invalid GPIO pin ${e} (RESOURCE_NOT_FOUND)\n Suggestion: Use a pin number between 0 and ${this.count-1}\n Path: /gpio/${e}/config`);return this.fetch(`/gpio/${e}/config`,{schema:N})}read_sync(){return this.fetch(`/gpio/sync`,{schema:p})}sequence(){return new L(this.fetch,this.count)}},F=class{fetch;id;constructor(e,t){this.fetch=e,this.id=t}configure_input(e){return this.fetch(`/gpio/${this.id}/config`,{method:`PATCH`,body:n.parse(o,{...e,mode:`digital`,direction:`input`}),schema:o})}configure_output(e){e=n.parse(l,e);let t={mode:`digital`,direction:`output`,value:e.value,vol:e.vol,voh:e.voh,vil:e.vil??e.vol+(e.voh-e.vol)/4,vih:e.vih??e.voh-(e.voh-e.vol)/4};return this.fetch(`/gpio/${this.id}/config`,{method:`PATCH`,body:n.parse(s,t),schema:s})}async read(){return(await this.fetch(`/gpio/${this.id}/state`,{schema:u})).value}async write(e){return(await this.fetch(`/gpio/${this.id}/state`,{method:`PUT`,body:n.parse(u,{value:e}),schema:u})).value}configure_open_drain(e){return this.fetch(`/gpio/${this.id}/config`,{method:`PATCH`,body:n.parse(c,{...e,mode:`digital`,direction:`open_drain`}),schema:c})}},I=class{fetch;id;constructor(e,t){this.fetch=e,this.id=t}configure_input(){return this.fetch(`/gpio/${this.id}/config`,{method:`PATCH`,body:{mode:`analog`,direction:`input`},schema:i})}configure_output(e){return this.fetch(`/gpio/${this.id}/config`,{method:`PATCH`,body:n.parse(a,{value:e,mode:`analog`,direction:`output`}),schema:a})}async read(){return(await this.fetch(`/gpio/${this.id}/state`,{schema:d})).value}async write(e){return(await this.fetch(`/gpio/${this.id}/state`,{method:`PUT`,body:{value:e},schema:d})).value}},L=class e{fetch;count;tail;constructor(e,t,n){this.fetch=e,this.count=t,this.tail=n}read(e,t){if(this.pinList(`read`,e),t?.delay!==void 0&&(t.repeat??1)<2)throw Error(`read() delay needs repeat of 2 or more`);return this.append({op:`read`,io:e,...t?.repeat===void 0?{}:{repeat:t.repeat},...t?.delay===void 0?{}:{delay:t.delay},...t?.expect===void 0?{}:{expect:t.expect}})}write(e,t){let n=this.pinList(`write`,e);if(Array.isArray(t)&&t.length!==n.length)throw Error(`write() got ${t.length} values for ${n.length} pins`);return this.append({op:`write`,io:e,value:t})}wait_voltage(e,t){this.check(e);let{min:n,max:r}=t;if(n===void 0&&r===void 0)throw Error(`wait_voltage() needs min, max, or both`);if(n!==void 0&&r!==void 0&&n>r)throw Error(`wait_voltage() min ${n} is above max ${r}`);return this.append({op:`wait_voltage`,io:e,...n===void 0?{}:{min:n},...r===void 0?{}:{max:r},...R(t)})}wait_level(e,t,n){return this.check(e),this.append({op:`wait_level`,io:e,level:z(t),...R(n)})}delay(e){return this.append({op:`delay`,duration:e})}hold(){return this.append({op:`hold`})}release(){return this.append({op:`release`})}as(t){if(typeof t!=`string`||t.length===0)throw Error(`Sequence name must be a nonempty string`);if(this.tail===void 0)throw Error(`No sequence command to name`);if(this.tail.name!==void 0)throw Error(`Sequence command is already named`);for(let e=this.tail;e;e=e.previous)if(e.name===t)throw Error(`Duplicate sequence name: ${t}`);return new e(this.fetch,this.count,{...this.tail,name:t})}run(e){if(this.tail===void 0)throw Error(`Sequence is empty`);let t=[];t.length=this.tail.length;let r=[];for(let e=this.tail;e;e=e.previous){let n=e.length-1;t[n]=e.command,e.name!==void 0&&r.push({name:e.name,index:n,command:e.command})}r.reverse();let i=e?.timeout??30;return this.fetch(`/gpio/sequence`,{method:`POST`,body:n.parse(T,{timeout:i,commands:t}),schema:n.pipe(O,n.check(e=>j(e,t),`Invalid GPIO sequence response`)),timeout:(i+2)*1e3}).then(e=>new k(e,r))}pinList(e,t){let n=typeof t==`number`?[t]:t;if(n.length===0)throw Error(`${e}() needs at least one pin`);for(let t of n)if(this.check(t),n.indexOf(t)!==n.lastIndexOf(t))throw Error(`${e}() lists pin ${t} twice`);return n}check(e){if(e<0||e>=this.count)throw Error(`Invalid GPIO pin ${e} (RESOURCE_NOT_FOUND)\n Suggestion: Use a pin number between 0 and ${this.count-1}\n Path: /gpio/sequence`)}append(t){if((this.tail?.length??0)>=65536)throw Error(`Sequence exceeds 65536 commands`);return new e(this.fetch,this.count,{command:n.parse(w,t),previous:this.tail,length:(this.tail?.length??0)+1})}};const R=e=>({...e?.timeout===void 0?{}:{timeout:e.timeout},...e?.stable_for===void 0?{}:{stable_for:e.stable_for}}),z=e=>typeof e==`boolean`?e?`high`:`low`:e;exports.AnalogIO=I,exports.DigitalIO=F,exports.GpioApi=P,exports.GpioSequence=L,exports.GpioSequenceReport=k,exports.analogInputConfiguration=i,exports.analogOutputConfiguration=a,exports.analogState=d,exports.digitalInputConfiguration=o,exports.digitalOutputConfiguration=s,exports.digitalState=u,exports.gpioConfiguration=N,exports.openDrainConfiguration=c,exports.syncState=p;
2
2
  //# sourceMappingURL=gpio.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"gpio.cjs","names":["v","analogOutputLevel","analogLevel","digitalLevel"],"sources":["../src/api/gpio.ts"],"sourcesContent":["import type { UpFetch } from 'up-fetch';\nimport * as v from 'valibot';\n\nimport { analogLevel, type AnalogOutputLevel, analogOutputLevel, digitalLevel } from './common';\nimport type { Information } from './management';\n\nexport type { AnalogOutputLevel };\n\nconst syncAction = v.picklist(['release', 'hold'], 'Invalid sync action');\nexport const analogInputConfiguration = v.object({\n mode: v.literal('analog'),\n direction: v.literal('input'),\n});\nexport const analogOutputConfiguration = v.object({\n mode: v.literal('analog'),\n direction: v.literal('output'),\n value: v.optional(analogOutputLevel),\n});\nexport const digitalInputConfiguration = v.object({\n mode: v.literal('digital'),\n direction: v.literal('input'),\n vil: analogLevel,\n vih: analogLevel,\n});\nexport const digitalOutputConfiguration = v.object({\n mode: v.literal('digital'),\n direction: v.literal('output'),\n value: digitalLevel,\n vol: analogOutputLevel,\n voh: analogOutputLevel,\n vil: analogLevel,\n vih: analogLevel,\n});\nexport const openDrainConfiguration = v.object({\n mode: v.literal('digital'),\n direction: v.literal('open_drain'),\n value: digitalLevel,\n vil: analogLevel,\n vih: analogLevel,\n});\nexport type AnalogInputConfiguration = v.InferOutput<typeof analogInputConfiguration>;\nexport type AnalogOutputConfiguration = v.InferOutput<typeof analogOutputConfiguration>;\nexport type DigitalInputConfiguration = v.InferOutput<typeof digitalInputConfiguration>;\nexport type DigitalOutputConfiguration = v.InferOutput<typeof digitalOutputConfiguration>;\nexport type OpenDrainConfiguration = v.InferOutput<typeof openDrainConfiguration>;\n\nconst partialAnalogOutputConfiguration = v.omit(analogOutputConfiguration, ['direction', 'mode']);\nexport type PartialAnalogOutputConfiguration = v.InferOutput<\n typeof partialAnalogOutputConfiguration\n>;\nconst partialDigitalInputConfiguration = v.omit(digitalInputConfiguration, ['direction', 'mode']);\nexport type PartialDigitalInputConfiguration = v.InferOutput<\n typeof partialDigitalInputConfiguration\n>;\nconst partialDigitalOutputConfiguration = v.partial(\n v.omit(digitalOutputConfiguration, ['direction', 'mode']),\n ['vih', 'vil'],\n);\nexport type PartialDigitalOutputConfiguration = v.InferInput<\n typeof partialDigitalOutputConfiguration\n>;\nconst partialOpenDrainConfiguration = v.omit(openDrainConfiguration, ['direction', 'mode']);\nexport type PartialOpenDrainConfiguration = v.InferOutput<typeof partialOpenDrainConfiguration>;\n\nexport const digitalState = v.object({ value: digitalLevel });\nexport const analogState = v.object({ value: analogLevel });\n\nconst syncConfiguration = v.object({ action: syncAction });\nexport type SyncConfiguration = v.InferOutput<typeof syncConfiguration>;\n\nexport const syncState = v.object({ hold_state: v.picklist(['held', 'released']) });\nexport type SyncState = v.InferOutput<typeof syncState>;\n\nexport const gpioConfiguration = v.union([\n digitalOutputConfiguration,\n openDrainConfiguration,\n digitalInputConfiguration,\n analogOutputConfiguration,\n analogInputConfiguration,\n]);\nexport type GpioConfiguration = v.InferOutput<typeof gpioConfiguration>;\n\n/** @hideconstructor */\nexport class GpioApi {\n private count: number;\n\n constructor(private readonly fetch: UpFetch, info: Information) {\n this.count = info.capabilities.io.count;\n }\n\n /**\n * Resets all IO configurations to default.\n */\n reset(): Promise<void> {\n return this.fetch('/gpio/reset', { method: 'POST', parseResponse: () => {} });\n }\n\n /**\n * Access a specific digital IO pin by id.\n * @param io The IO pin id.\n * @returns The digital IO instance.\n */\n digital(io: number): DigitalIO {\n if (io < 0 || io >= this.count) {\n throw new Error(\n `Invalid GPIO pin ${io} (RESOURCE_NOT_FOUND)\\n Suggestion: Use a pin number between 0 and ${\n this.count - 1\n }\\n Path: /gpio/${io}`,\n );\n }\n\n return new DigitalIO(this.fetch, io);\n }\n\n /**\n * Access a specific analog IO pin by id.\n * @param io The IO pin id.\n * @returns The analog IO instance.\n */\n analog(io: number): AnalogIO {\n if (io < 0 || io >= this.count) {\n throw new Error(\n `Invalid GPIO pin ${io} (RESOURCE_NOT_FOUND)\\n Suggestion: Use a pin number between 0 and ${\n this.count - 1\n }\\n Path: /gpio/${io}`,\n );\n }\n\n return new AnalogIO(this.fetch, io);\n }\n\n /**\n * Holds the current state of all GPIO pins.\n * @returns The applied sync state.\n */\n hold(): Promise<SyncConfiguration> {\n return this.fetch('/gpio/sync', {\n method: 'POST',\n body: { action: 'hold' } satisfies SyncConfiguration,\n schema: syncConfiguration,\n });\n }\n\n /**\n * Releases control of the IO pins, allowing external control.\n *\n * This also sets the device as a slave.\n *\n * @returns The applied sync state.\n */\n release(): Promise<SyncConfiguration> {\n return this.fetch('/gpio/sync', {\n method: 'POST',\n body: { action: 'release' } satisfies SyncConfiguration,\n schema: syncConfiguration,\n });\n }\n\n /**\n * Reads back the current configuration of a specific IO pin.\n * @param io The IO pin id.\n * @returns The pin's current configuration.\n */\n read_config(io: number): Promise<GpioConfiguration> {\n if (io < 0 || io >= this.count) {\n throw new Error(\n `Invalid GPIO pin ${io} (RESOURCE_NOT_FOUND)\\n Suggestion: Use a pin number between 0 and ${\n this.count - 1\n }\\n Path: /gpio/${io}/config`,\n );\n }\n\n return this.fetch(`/gpio/${io}/config`, { schema: gpioConfiguration });\n }\n\n /**\n * Reads the current hold state of all GPIO pins.\n * @returns The current sync state.\n */\n read_sync(): Promise<SyncState> {\n return this.fetch('/gpio/sync', { schema: syncState });\n }\n}\n\n/** @hideconstructor */\nexport class DigitalIO {\n constructor(private readonly fetch: UpFetch, public readonly id: number) {}\n\n /**\n * Configure the pin as a digital input.\n * @param config The digital input configuration.\n * @returns The applied configuration.\n */\n configure_input(config: PartialDigitalInputConfiguration): Promise<DigitalInputConfiguration> {\n return this.fetch(`/gpio/${this.id}/config`, {\n method: 'PATCH',\n body: v.parse(\n digitalInputConfiguration,\n { ...config, mode: 'digital', direction: 'input' } satisfies DigitalInputConfiguration,\n ),\n schema: digitalInputConfiguration,\n });\n }\n\n /**\n * Configures the pin as a digital output.\n * @param config The digital output configuration.\n * @returns The applied configuration.\n */\n configure_output(config: PartialDigitalOutputConfiguration): Promise<DigitalOutputConfiguration> {\n config = v.parse(partialDigitalOutputConfiguration, config);\n\n const fullConfig = {\n mode: 'digital' as const,\n direction: 'output' as const,\n value: config.value,\n vol: config.vol,\n voh: config.voh,\n vil: config.vil ?? config.vol + (config.voh - config.vol) / 4,\n vih: config.vih ?? config.voh - (config.voh - config.vol) / 4,\n };\n\n return this.fetch(`/gpio/${this.id}/config`, {\n method: 'PATCH',\n body: v.parse(digitalOutputConfiguration, fullConfig),\n schema: digitalOutputConfiguration,\n });\n }\n\n /**\n * Reads the current state of the pin.\n * @returns The current state of the pin.\n */\n async read(): Promise<boolean> {\n return (await this.fetch(`/gpio/${this.id}/state`, { schema: digitalState })).value;\n }\n\n /**\n * Writes a value to the pin.\n * @param value The value to write.\n * @returns The written value.\n */\n async write(value: boolean | number): Promise<boolean> {\n return (await this.fetch(`/gpio/${this.id}/state`, {\n method: 'PUT',\n body: v.parse(digitalState, { value }),\n schema: digitalState,\n }))\n .value;\n }\n\n /**\n * Configure the pin as an open drain output.\n * @param config The open drain configuration.\n * @returns The applied configuration.\n */\n configure_open_drain(config: PartialOpenDrainConfiguration): Promise<OpenDrainConfiguration> {\n return this.fetch(`/gpio/${this.id}/config`, {\n method: 'PATCH',\n body: v.parse(\n openDrainConfiguration,\n { ...config, mode: 'digital', direction: 'open_drain' } satisfies OpenDrainConfiguration,\n ),\n schema: openDrainConfiguration,\n });\n }\n}\n\n/** @hideconstructor */\nexport class AnalogIO {\n constructor(private readonly fetch: UpFetch, public readonly id: number) {}\n\n /**\n * Configures the pin as an analog input.\n * @returns The applied configuration.\n * @returns The applied configuration.\n */\n configure_input(): Promise<AnalogInputConfiguration> {\n return this.fetch(`/gpio/${this.id}/config`, {\n method: 'PATCH',\n body: { mode: 'analog', direction: 'input' } satisfies AnalogInputConfiguration,\n schema: analogInputConfiguration,\n });\n }\n\n /**\n * Configures the pin as an analog output.\n * @param config The analog output configuration.\n * @returns The applied configuration.\n */\n configure_output(value: AnalogOutputLevel): Promise<AnalogOutputConfiguration> {\n return this.fetch(`/gpio/${this.id}/config`, {\n method: 'PATCH',\n body: v.parse(\n analogOutputConfiguration,\n { value, mode: 'analog', direction: 'output' } satisfies AnalogOutputConfiguration,\n ),\n schema: analogOutputConfiguration,\n });\n }\n\n /**\n * Reads the current state of the pin.\n * @returns The current state of the pin.\n */\n async read(): Promise<number> {\n return (await this.fetch(`/gpio/${this.id}/state`, { schema: analogState })).value;\n }\n\n /**\n * Writes a value to the pin.\n * @param value The value to write.\n * @returns The written value.\n */\n async write(value: number): Promise<number> {\n return (await this.fetch(`/gpio/${this.id}/state`, {\n method: 'PUT',\n body: { value },\n schema: analogState,\n }))\n .value;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"gpio.cjs","names":["v","analogOutputLevel","analogLevel","digitalLevel"],"sources":["../src/api/gpio.ts"],"sourcesContent":["import type { UpFetch } from 'up-fetch';\nimport * as v from 'valibot';\n\nimport { type AnalogOutputLevel, analogLevel, analogOutputLevel, digitalLevel } from './common';\nimport type { Information } from './management';\n\nexport type { AnalogOutputLevel };\n\nconst syncAction = v.picklist(['release', 'hold'], 'Invalid sync action');\nexport const analogInputConfiguration = v.object({\n mode: v.literal('analog'),\n direction: v.literal('input'),\n});\nexport const analogOutputConfiguration = v.object({\n mode: v.literal('analog'),\n direction: v.literal('output'),\n value: v.optional(analogOutputLevel),\n});\n/**\n * Input thresholds `vil` and `vih` are in [-25, 25] V, inclusive.\n */\nexport const digitalInputConfiguration = v.object({\n mode: v.literal('digital'),\n direction: v.literal('input'),\n vil: analogLevel,\n vih: analogLevel,\n});\n/**\n * Readback thresholds `vil` and `vih` are in [-25, 25] V, inclusive.\n * Output levels `vol` and `voh` are in [0, 24] V, inclusive.\n */\nexport const digitalOutputConfiguration = v.object({\n mode: v.literal('digital'),\n direction: v.literal('output'),\n value: digitalLevel,\n vol: analogOutputLevel,\n voh: analogOutputLevel,\n vil: analogLevel,\n vih: analogLevel,\n});\n/**\n * Readback thresholds `vil` and `vih` are in [-25, 25] V, inclusive.\n */\nexport const openDrainConfiguration = v.object({\n mode: v.literal('digital'),\n direction: v.literal('open_drain'),\n value: digitalLevel,\n vil: analogLevel,\n vih: analogLevel,\n});\nexport type AnalogInputConfiguration = v.InferOutput<typeof analogInputConfiguration>;\nexport type AnalogOutputConfiguration = v.InferOutput<typeof analogOutputConfiguration>;\nexport type DigitalInputConfiguration = v.InferOutput<typeof digitalInputConfiguration>;\nexport type DigitalOutputConfiguration = v.InferOutput<typeof digitalOutputConfiguration>;\nexport type OpenDrainConfiguration = v.InferOutput<typeof openDrainConfiguration>;\n\nconst partialAnalogOutputConfiguration = v.omit(analogOutputConfiguration, ['direction', 'mode']);\nexport type PartialAnalogOutputConfiguration = v.InferOutput<\n typeof partialAnalogOutputConfiguration\n>;\nconst partialDigitalInputConfiguration = v.omit(digitalInputConfiguration, ['direction', 'mode']);\nexport type PartialDigitalInputConfiguration = v.InferOutput<\n typeof partialDigitalInputConfiguration\n>;\nconst partialDigitalOutputConfiguration = v.partial(\n v.omit(digitalOutputConfiguration, ['direction', 'mode']),\n ['vih', 'vil'],\n);\nexport type PartialDigitalOutputConfiguration = v.InferInput<\n typeof partialDigitalOutputConfiguration\n>;\nconst partialOpenDrainConfiguration = v.omit(openDrainConfiguration, ['direction', 'mode']);\nexport type PartialOpenDrainConfiguration = v.InferOutput<typeof partialOpenDrainConfiguration>;\n\nexport const digitalState = v.object({ value: digitalLevel });\nexport const analogState = v.object({ value: analogLevel });\n\nconst syncConfiguration = v.object({ action: syncAction });\nexport type SyncConfiguration = v.InferOutput<typeof syncConfiguration>;\n\nexport const syncState = v.object({ hold_state: v.picklist(['held', 'released']) });\nexport type SyncState = v.InferOutput<typeof syncState>;\n\nconst sequenceOp = v.picklist([\n 'read',\n 'write',\n 'wait_voltage',\n 'wait_level',\n 'delay',\n 'hold',\n 'release',\n]);\nconst sequenceDuration = v.pipe(v.number(), v.finite(), v.minValue(Number.MIN_VALUE));\nconst sequenceIo = v.pipe(v.number(), v.integer(), v.minValue(0), v.maxValue(31));\nconst sequencePins = v.union([sequenceIo, v.pipe(v.array(sequenceIo), v.minLength(1))]);\n// A digital level or a voltage: the device decides from the pin's configured mode.\n// Numbers stay in [0, 24] because the same field carries volts, so a numeric digital\n// level uses 0 for low and anything else for high.\nconst sequenceValue = v.union([v.boolean(), analogOutputLevel]);\n// One value for every listed pin, or one value per pin paired with the pin list.\nconst sequenceValues = v.union([sequenceValue, v.pipe(v.array(sequenceValue), v.minLength(1))]);\nconst sequenceRepeat = v.pipe(v.number(), v.integer(), v.minValue(1));\nconst sequenceBounds = v.object({ min: analogLevel, max: analogLevel });\nconst sequenceLevel = v.picklist(['low', 'high'], 'Invalid level');\nconst sequenceExpect = v.union([v.boolean(), sequenceBounds]);\nconst sequenceCommand = v.variant('op', [\n v.object({\n op: v.literal('read'),\n io: sequencePins,\n repeat: v.optional(sequenceRepeat),\n delay: v.optional(sequenceDuration),\n expect: v.optional(sequenceExpect),\n }),\n v.object({ op: v.literal('write'), io: sequencePins, value: sequenceValues }),\n v.object({\n op: v.literal('wait_voltage'),\n io: sequenceIo,\n min: v.optional(analogLevel),\n max: v.optional(analogLevel),\n timeout: v.optional(sequenceDuration),\n stable_for: v.optional(sequenceDuration),\n }),\n v.object({\n op: v.literal('wait_level'),\n io: sequenceIo,\n level: sequenceLevel,\n timeout: v.optional(sequenceDuration),\n stable_for: v.optional(sequenceDuration),\n }),\n v.object({ op: v.literal('delay'), duration: sequenceDuration }),\n v.object({ op: v.literal('hold') }),\n v.object({ op: v.literal('release') }),\n]);\nconst sequenceRequest = v.object({\n timeout: sequenceDuration,\n commands: v.pipe(v.array(sequenceCommand), v.minLength(1), v.maxLength(65536)),\n});\nconst sequenceSample = v.object({\n io: v.number(),\n value: v.union([v.boolean(), v.number()]),\n elapsed: v.number(),\n});\nconst sequenceStep = v.object({\n op: sequenceOp,\n io: v.optional(v.union([v.number(), v.array(v.number())])),\n value: v.optional(v.union([v.boolean(), v.number()])),\n samples: v.optional(v.array(sequenceSample)),\n elapsed: v.number(),\n});\nconst sequenceReport = v.object({ elapsed: v.number(), results: v.array(sequenceStep) });\n\nexport type GpioSequenceCommand = v.InferOutput<typeof sequenceCommand>;\nexport type GpioSequenceSample = v.InferOutput<typeof sequenceSample>;\n/**\n * Result of one command.\n *\n * `value` carries a single-valued step — an ordinary read of one pin with no repeat, or\n * a write of one pin — while `samples` carries a step that covered several pins or\n * repeated: the readings of a `read`, or the values a `write` applied.\n */\nexport type GpioSequenceStep = v.InferOutput<typeof sequenceStep>;\ntype SequenceWireReport = v.InferOutput<typeof sequenceReport>;\ntype SequenceKind = 'scalar' | 'collection' | 'control';\ntype SequenceDescriptor<\n Op extends GpioSequenceCommand['op'] = GpioSequenceCommand['op'],\n Kind extends SequenceKind = SequenceKind,\n> = { op: Op; kind: Kind };\ntype SequenceMetadata<Op> = { name: string; index: number; op: Op };\ntype SequenceAttempt<Op> = SequenceMetadata<Op> & { elapsed: number };\ntype SequenceScalar<Op> = SequenceAttempt<Op> & {\n kind: 'scalar';\n io: number | number[];\n value: boolean | number;\n};\ntype SequenceCollection<Op> = SequenceAttempt<Op> & {\n kind: 'collection';\n io: number | number[];\n samples: GpioSequenceSample[];\n};\ntype SequenceControl<Op> = SequenceAttempt<Op> & { kind: 'control' };\ntype SequenceResultForKind<Op, Kind> = Kind extends 'scalar' ? SequenceScalar<Op>\n : Kind extends 'collection' ? SequenceCollection<Op>\n : SequenceControl<Op>;\ntype SequenceResult<Descriptor> = Descriptor extends SequenceDescriptor<infer Op, infer Kind>\n ? SequenceResultForKind<Op, Kind>\n : never;\ntype SequenceDescriptors =\n | SequenceDescriptor<'read' | 'write', 'scalar' | 'collection'>\n | SequenceDescriptor<'wait_voltage' | 'wait_level', 'scalar'>\n | SequenceDescriptor<'hold' | 'release' | 'delay', 'control'>;\nexport type GpioSequenceNamedResult = SequenceResult<SequenceDescriptors>;\ntype SequenceNamed<Names> = { readonly [Name in keyof Names]: SequenceResult<Names[Name]> };\ntype SequenceAssociation = { name: string; index: number; command: GpioSequenceCommand };\n\n/** Raw results remain in command order. Names are local to this run. */\nexport class GpioSequenceReport<Names = {}> {\n readonly elapsed: number;\n readonly results: GpioSequenceStep[];\n readonly named: SequenceNamed<Names>;\n readonly #lookup: Readonly<Record<string, GpioSequenceNamedResult>>;\n\n /** Constructing a bare wire report does not restore command names. */\n constructor(wire: SequenceWireReport, associations: readonly SequenceAssociation[] = []) {\n this.elapsed = wire.elapsed;\n this.results = wire.results;\n const named: Record<string, GpioSequenceNamedResult> = Object.create(null);\n for (const association of associations) {\n const result = namedSequenceResult(association, wire.results[association.index]);\n named[association.name] = result;\n }\n this.named = Object.freeze(named) as SequenceNamed<Names>;\n this.#lookup = named;\n }\n\n get(name: string): GpioSequenceNamedResult | undefined {\n return this.#lookup[name];\n }\n\n toJSON(): SequenceWireReport {\n return { elapsed: this.elapsed, results: this.results };\n }\n}\n\nconst sequenceKind = (command: GpioSequenceCommand): SequenceKind => {\n switch (command.op) {\n case 'read':\n return Array.isArray(command.io) || (command.repeat ?? 1) > 1 ? 'collection' : 'scalar';\n case 'write':\n return Array.isArray(command.io) && command.io.length > 1 ? 'collection' : 'scalar';\n case 'wait_voltage':\n case 'wait_level':\n return 'scalar';\n default:\n return 'control';\n }\n};\n\nconst matchesSequence = (report: SequenceWireReport, commands: GpioSequenceCommand[]): boolean => {\n if (report.results.length !== commands.length) return false;\n return report.results.every((step, index) => {\n const command = commands[index];\n if (step.op !== command.op) return false;\n const io = 'io' in command ? command.io : undefined;\n if (Array.isArray(io)) {\n if (!Array.isArray(step.io) || io.length !== step.io.length) return false;\n if (!io.every((pin, offset) => pin === (step.io as number[])[offset])) return false;\n } else if (step.io !== io) {\n return false;\n }\n const kind = sequenceKind(command);\n if (kind === 'control') return step.value === undefined && step.samples === undefined;\n if (kind === 'scalar') return step.samples === undefined && step.value !== undefined;\n const pins = Array.isArray(io) ? io : [io];\n const count = pins.length * (command.op === 'read' ? command.repeat ?? 1 : 1);\n // A `read` of a one-element pin list with no repeat still comes back as a plain\n // value: the device only details a step that covered several readings.\n const singleton = command.op === 'read' && count === 1 && step.value !== undefined\n && step.samples === undefined;\n if (singleton) return true;\n if (step.value !== undefined) return false;\n const samples = step.samples ?? [];\n if (samples.length !== count) return false;\n return samples.every((sample, offset) => sample.io === pins[offset % pins.length]);\n });\n};\n\nconst namedSequenceResult = (\n { name, index, command }: SequenceAssociation,\n step: GpioSequenceStep,\n): GpioSequenceNamedResult => {\n const attempt = { name, index, op: command.op, elapsed: step.elapsed };\n switch (sequenceKind(command)) {\n case 'scalar':\n return {\n ...attempt,\n kind: 'scalar',\n io: step.io,\n value: step.value,\n } as GpioSequenceNamedResult;\n case 'collection':\n return {\n ...attempt,\n kind: 'collection',\n io: step.io,\n // A correlated one-reading collection carries its lone reading in `value`.\n samples: step.samples\n ?? [{ io: (step.io as number[])[0], value: step.value, elapsed: step.elapsed }],\n } as GpioSequenceNamedResult;\n default:\n return { ...attempt, kind: 'control' } as GpioSequenceNamedResult;\n }\n};\n\ntype SequenceReadRepeat<Options> = Options extends GpioSequenceReadOptions\n ? 'repeat' extends keyof Options ? Options['repeat'] : undefined\n : undefined;\ntype SequenceReadKind<Pins, Repeat> = Pins extends readonly number[] ? 'collection'\n : Repeat extends undefined | 1 ? 'scalar'\n : number extends Repeat ? 'scalar' | 'collection'\n : 'collection';\ntype SequenceWriteKind<Pins> = Pins extends readonly number[]\n ? number extends Pins['length'] ? 'scalar' | 'collection'\n : Pins['length'] extends 1 ? 'scalar' : 'collection'\n : 'scalar';\ntype SequenceWithName<Names, Name extends string, Last> = string extends Name ? Names\n : Name extends string ? Names & { [Key in Name]: Last }\n : never;\ntype SequenceNode = {\n readonly command: GpioSequenceCommand;\n readonly name?: string;\n readonly previous?: SequenceNode;\n readonly length: number;\n};\n/** A digital level, or inclusive voltage bounds for an analog pin. */\nexport type GpioSequenceExpectation = v.InferOutput<typeof sequenceExpect>;\n/** A digital level, or a voltage for an analog pin. */\nexport type GpioSequenceValue = v.InferOutput<typeof sequenceValue>;\nexport type GpioSequenceReadOptions = {\n repeat?: number;\n delay?: number;\n expect?: GpioSequenceExpectation;\n};\n/** A digital level: the strings the wire uses, or a boolean (`true` is high). */\nexport type GpioSequenceLevel = 'low' | 'high' | boolean;\nexport type GpioSequenceWaitOptions = { timeout?: number; stable_for?: number };\n/** At least one edge is required; both together are an inclusive band. */\nexport type GpioSequenceWaitVoltageOptions =\n & ({ min: number; max?: number } | { max: number; min?: number })\n & GpioSequenceWaitOptions;\n\nexport const gpioConfiguration = v.union([\n digitalOutputConfiguration,\n openDrainConfiguration,\n digitalInputConfiguration,\n analogOutputConfiguration,\n analogInputConfiguration,\n]);\nexport type GpioConfiguration = v.InferOutput<typeof gpioConfiguration>;\n\n/** @hideconstructor */\nexport class GpioApi {\n private count: number;\n\n constructor(private readonly fetch: UpFetch, info: Information) {\n this.count = info.capabilities.io.count;\n }\n\n /**\n * Resets all IO configurations to default.\n */\n reset(): Promise<void> {\n return this.fetch('/gpio/reset', { method: 'POST', parseResponse: () => {} });\n }\n\n /**\n * Access a specific digital IO pin by id.\n * @param io The IO pin id.\n * @returns The digital IO instance.\n */\n digital(io: number): DigitalIO {\n if (io < 0 || io >= this.count) {\n throw new Error(\n `Invalid GPIO pin ${io} (RESOURCE_NOT_FOUND)\\n Suggestion: Use a pin number between 0 and ${\n this.count - 1\n }\\n Path: /gpio/${io}`,\n );\n }\n\n return new DigitalIO(this.fetch, io);\n }\n\n /**\n * Access a specific analog IO pin by id.\n * @param io The IO pin id.\n * @returns The analog IO instance.\n */\n analog(io: number): AnalogIO {\n if (io < 0 || io >= this.count) {\n throw new Error(\n `Invalid GPIO pin ${io} (RESOURCE_NOT_FOUND)\\n Suggestion: Use a pin number between 0 and ${\n this.count - 1\n }\\n Path: /gpio/${io}`,\n );\n }\n\n return new AnalogIO(this.fetch, io);\n }\n\n /**\n * Holds the current state of all GPIO pins.\n * @returns The applied sync state.\n */\n hold(): Promise<SyncConfiguration> {\n return this.fetch('/gpio/sync', {\n method: 'POST',\n body: { action: 'hold' } satisfies SyncConfiguration,\n schema: syncConfiguration,\n });\n }\n\n /**\n * Releases control of the IO pins, allowing external control.\n *\n * This also sets the device as a slave.\n *\n * @returns The applied sync state.\n */\n release(): Promise<SyncConfiguration> {\n return this.fetch('/gpio/sync', {\n method: 'POST',\n body: { action: 'release' } satisfies SyncConfiguration,\n schema: syncConfiguration,\n });\n }\n\n /**\n * Reads back the current configuration of a specific IO pin.\n * @param io The IO pin id.\n * @returns The pin's current configuration.\n */\n read_config(io: number): Promise<GpioConfiguration> {\n if (io < 0 || io >= this.count) {\n throw new Error(\n `Invalid GPIO pin ${io} (RESOURCE_NOT_FOUND)\\n Suggestion: Use a pin number between 0 and ${\n this.count - 1\n }\\n Path: /gpio/${io}/config`,\n );\n }\n\n return this.fetch(`/gpio/${io}/config`, { schema: gpioConfiguration });\n }\n\n /**\n * Reads the current hold state of all GPIO pins.\n * @returns The current sync state.\n */\n read_sync(): Promise<SyncState> {\n return this.fetch('/gpio/sync', { schema: syncState });\n }\n\n /**\n * Starts a command sequence.\n *\n * The device runs every appended command back to back, holding the IO subsystem for\n * the whole run, so no other IO request interleaves. Every pin used must be\n * configured before `run()`.\n *\n * @returns An empty sequence builder.\n */\n sequence(): GpioSequence {\n return new GpioSequence(this.fetch, this.count);\n }\n}\n\n/** @hideconstructor */\nexport class DigitalIO {\n constructor(private readonly fetch: UpFetch, public readonly id: number) {}\n\n /**\n * Configure the pin as a digital input.\n * @param config The digital input configuration.\n * @returns The applied configuration.\n */\n configure_input(config: PartialDigitalInputConfiguration): Promise<DigitalInputConfiguration> {\n return this.fetch(`/gpio/${this.id}/config`, {\n method: 'PATCH',\n body: v.parse(\n digitalInputConfiguration,\n { ...config, mode: 'digital', direction: 'input' } satisfies DigitalInputConfiguration,\n ),\n schema: digitalInputConfiguration,\n });\n }\n\n /**\n * Configures the pin as a digital output.\n * @param config The digital output configuration.\n * @returns The applied configuration.\n */\n configure_output(config: PartialDigitalOutputConfiguration): Promise<DigitalOutputConfiguration> {\n config = v.parse(partialDigitalOutputConfiguration, config);\n\n const fullConfig = {\n mode: 'digital' as const,\n direction: 'output' as const,\n value: config.value,\n vol: config.vol,\n voh: config.voh,\n vil: config.vil ?? config.vol + (config.voh - config.vol) / 4,\n vih: config.vih ?? config.voh - (config.voh - config.vol) / 4,\n };\n\n return this.fetch(`/gpio/${this.id}/config`, {\n method: 'PATCH',\n body: v.parse(digitalOutputConfiguration, fullConfig),\n schema: digitalOutputConfiguration,\n });\n }\n\n /**\n * Reads the current state of the pin.\n * @returns The current state of the pin.\n */\n async read(): Promise<boolean> {\n return (await this.fetch(`/gpio/${this.id}/state`, { schema: digitalState })).value;\n }\n\n /**\n * Writes a value to the pin.\n * @param value The value to write.\n * @returns The written value.\n */\n async write(value: boolean | number): Promise<boolean> {\n return (await this.fetch(`/gpio/${this.id}/state`, {\n method: 'PUT',\n body: v.parse(digitalState, { value }),\n schema: digitalState,\n }))\n .value;\n }\n\n /**\n * Configure the pin as an open drain output.\n * @param config The open drain configuration.\n * @returns The applied configuration.\n */\n configure_open_drain(config: PartialOpenDrainConfiguration): Promise<OpenDrainConfiguration> {\n return this.fetch(`/gpio/${this.id}/config`, {\n method: 'PATCH',\n body: v.parse(\n openDrainConfiguration,\n { ...config, mode: 'digital', direction: 'open_drain' } satisfies OpenDrainConfiguration,\n ),\n schema: openDrainConfiguration,\n });\n }\n}\n\n/** @hideconstructor */\nexport class AnalogIO {\n constructor(private readonly fetch: UpFetch, public readonly id: number) {}\n\n /**\n * Configures the pin as an analog input.\n * @returns The applied configuration.\n * @returns The applied configuration.\n */\n configure_input(): Promise<AnalogInputConfiguration> {\n return this.fetch(`/gpio/${this.id}/config`, {\n method: 'PATCH',\n body: { mode: 'analog', direction: 'input' } satisfies AnalogInputConfiguration,\n schema: analogInputConfiguration,\n });\n }\n\n /**\n * Configures the pin as an analog output.\n * @param config The analog output configuration.\n * @returns The applied configuration.\n */\n configure_output(value: AnalogOutputLevel): Promise<AnalogOutputConfiguration> {\n return this.fetch(`/gpio/${this.id}/config`, {\n method: 'PATCH',\n body: v.parse(\n analogOutputConfiguration,\n { value, mode: 'analog', direction: 'output' } satisfies AnalogOutputConfiguration,\n ),\n schema: analogOutputConfiguration,\n });\n }\n\n /**\n * Reads the current state of the pin.\n * @returns The current state of the pin.\n */\n async read(): Promise<number> {\n return (await this.fetch(`/gpio/${this.id}/state`, { schema: analogState })).value;\n }\n\n /**\n * Writes a value to the pin.\n * @param value The value to write.\n * @returns The written value.\n */\n async write(value: number): Promise<number> {\n return (await this.fetch(`/gpio/${this.id}/state`, {\n method: 'PUT',\n body: { value },\n schema: analogState,\n }))\n .value;\n }\n}\n\n/**\n * A list of IO commands the device runs back to back.\n *\n * Nothing is sent until `run()`. `repeat`, `delay`, `expect` and `stable_for` are\n * device-side parameters: the builder never expands one appended command into several,\n * and never loops client-side. A builder is reusable — `run()` keeps the commands, so\n * the same sequence can be run again.\n *\n * @hideconstructor\n */\nexport class GpioSequence<Names = {}, Last = never> {\n constructor(\n private readonly fetch: UpFetch,\n private readonly count: number,\n private readonly tail?: SequenceNode,\n ) {}\n\n /**\n * Reads one pin, or several pins in the order given.\n *\n * `repeat` is the total number of readings of the whole pin list (1 when omitted) and\n * `delay` is the gap in seconds between passes: the first pass runs immediately, every\n * later pass waits `delay`, nothing waits after the last one, and nothing waits\n * between the pins of one pass. It is an end-to-start gap, not a sampling interval,\n * so the effective period is `delay` plus however long a pass takes. `expect` is\n * asserted on every reading: a boolean needs digital pins, inclusive `{ min, max }`\n * volts needs analog pins. A failed assertion fails the whole run with\n * `SEQUENCE_ASSERTION_FAILED`.\n *\n * @param io The pin, or the distinct pins to read in order.\n * @param options Repetition, inter-pass gap and assertion.\n * @returns An independent builder with this command appended.\n */\n read<\n const Pins extends number | readonly number[],\n const Options extends GpioSequenceReadOptions | undefined = undefined,\n >(\n io: Pins,\n options?: Options,\n ): GpioSequence<\n Names,\n SequenceDescriptor<'read', SequenceReadKind<Pins, SequenceReadRepeat<Options>>>\n > {\n this.pinList('read', io);\n if (options?.delay !== undefined && (options.repeat ?? 1) < 2) {\n throw new Error('read() delay needs repeat of 2 or more');\n }\n\n return this.append({\n op: 'read',\n io,\n ...(options?.repeat === undefined ? {} : { repeat: options.repeat }),\n ...(options?.delay === undefined ? {} : { delay: options.delay }),\n ...(options?.expect === undefined ? {} : { expect: options.expect }),\n });\n }\n\n /**\n * Writes one pin, or several pins in the order given.\n *\n * A single `value` is applied to every listed pin; an array pairs one value per pin,\n * in the order of `io`, and must be exactly as long as the pin list. Each pin's\n * configured mode decides what its value means, exactly like the per-pin API: on a\n * digital pin a number is a level (`0` low, anything else high), on an analog pin a\n * number is volts, and a boolean written to an analog pin is rejected by the device.\n * The pins are independent, so one command may mix a digital level and an analog\n * voltage. Closed-loop output correction still runs per pin, so a multi-pin analog\n * write costs one correction per pin. Writing a pin several times, or spacing writes\n * out, means appending more `write` commands with `delay()` between them.\n *\n * A write of one pin reports the applied `value`; a write of several reports\n * `samples`, one entry per pin in the order they were driven.\n *\n * @param io The pin, or the distinct pins to write in order.\n * @param value The value applied to every pin, or one value per pin.\n * @returns An independent builder with this command appended.\n */\n write<const Pins extends number | readonly number[]>(\n io: Pins,\n value: GpioSequenceValue | readonly GpioSequenceValue[],\n ): GpioSequence<Names, SequenceDescriptor<'write', SequenceWriteKind<Pins>>> {\n const pins = this.pinList('write', io);\n if (Array.isArray(value) && value.length !== pins.length) {\n throw new Error(`write() got ${value.length} values for ${pins.length} pins`);\n }\n\n return this.append({ op: 'write', io, value });\n }\n\n /**\n * Waits for an analog pin to read inside a voltage bound.\n *\n * The pin must be in `analog` mode; the device rejects a digital one, which\n * {@link GpioSequence.wait_level} handles instead. `min` alone waits for the pin to\n * read at or above it, `max` alone for at or below it, and the two together for the\n * inclusive band they describe; at least one is required and `min` must not be above\n * `max`. The semantics are on the sample, not the edge, so a pin already inside the\n * bound completes immediately. `stable_for` (seconds) requires the bound to hold\n * across samples spanning that long; any sample outside it restarts the window.\n * Voltages come from polled ADC samples, so an excursion shorter than the interval\n * between two samples is invisible. A wait that exceeds its `timeout` fails the whole\n * run with `SEQUENCE_TIMED_OUT`.\n *\n * @param io The pin to watch.\n * @param options The bound edges in volts, time budget and stability window.\n * @returns An independent builder with this command appended.\n */\n wait_voltage(\n io: number,\n options: GpioSequenceWaitVoltageOptions,\n ): GpioSequence<Names, SequenceDescriptor<'wait_voltage', 'scalar'>> {\n this.check(io);\n const { min, max }: { min?: number; max?: number } = options;\n if (min === undefined && max === undefined) {\n throw new Error('wait_voltage() needs min, max, or both');\n }\n if (min !== undefined && max !== undefined && min > max) {\n throw new Error(`wait_voltage() min ${min} is above max ${max}`);\n }\n\n return this.append({\n op: 'wait_voltage',\n io,\n ...(min === undefined ? {} : { min }),\n ...(max === undefined ? {} : { max }),\n ...waitFields(options),\n });\n }\n\n /**\n * Waits for a digital pin to read a level.\n *\n * The pin must be in `digital` mode; the device rejects an analog one, which\n * {@link GpioSequence.wait_voltage} handles instead. The level is resolved from the\n * pin's configured `vil`/`vih`. The semantics are on the level, not the edge, so a pin\n * that already reads the level completes immediately. `stable_for` (seconds) requires\n * the level to hold across samples spanning that long; any sample that fails the\n * condition restarts the window. Levels come from polled ADC samples, so a transition\n * shorter than the interval between two samples is invisible. A wait that exceeds its\n * `timeout` fails the whole run with `SEQUENCE_TIMED_OUT`.\n *\n * @param io The pin to watch.\n * @param level The level to wait for, as `'low'`/`'high'` or a boolean.\n * @param options Time budget and stability window.\n * @returns An independent builder with this command appended.\n */\n wait_level(\n io: number,\n level: GpioSequenceLevel,\n options?: GpioSequenceWaitOptions,\n ): GpioSequence<Names, SequenceDescriptor<'wait_level', 'scalar'>> {\n this.check(io);\n return this.append({ op: 'wait_level', io, level: wireLevel(level), ...waitFields(options) });\n }\n\n /**\n * Sleeps, holding the IO subsystem.\n * @param duration Seconds to sleep.\n * @returns An independent builder with this command appended.\n */\n delay(duration: number): GpioSequence<Names, SequenceDescriptor<'delay', 'control'>> {\n return this.append({ op: 'delay', duration });\n }\n\n /**\n * Holds synchronization, freezing the analog outputs for the rest of the sequence.\n * @returns An independent builder with this command appended.\n */\n hold(): GpioSequence<Names, SequenceDescriptor<'hold', 'control'>> {\n return this.append({ op: 'hold' });\n }\n\n /**\n * Releases synchronization, applying every output staged while it was held.\n * @returns An independent builder with this command appended.\n */\n release(): GpioSequence<Names, SequenceDescriptor<'release', 'control'>> {\n return this.append({ op: 'release' });\n }\n\n /** Names the preceding command without changing this builder or the wire request. */\n as<const Name extends string>(\n name: Name & ([Last] extends [never] ? never : Name extends keyof Names ? never : unknown),\n ): GpioSequence<SequenceWithName<Names, Name, Last>, never> {\n if (typeof name !== 'string' || name.length === 0) {\n throw new Error('Sequence name must be a nonempty string');\n }\n if (this.tail === undefined) throw new Error('No sequence command to name');\n if (this.tail.name !== undefined) throw new Error('Sequence command is already named');\n for (let node: SequenceNode | undefined = this.tail; node; node = node.previous) {\n if (node.name === name) throw new Error(`Duplicate sequence name: ${name}`);\n }\n return new GpioSequence(this.fetch, this.count, { ...this.tail, name });\n }\n\n /**\n * Runs the sequence on the device.\n *\n * A wait that times out, a sequence that exceeds its budget and a failed read\n * assertion reject with an `ApiError` whose `code` is `SEQUENCE_TIMED_OUT` or\n * `SEQUENCE_ASSERTION_FAILED`; nothing after the stopping command runs, and no\n * partial report is produced.\n *\n * @param options Total time budget in seconds, 30 when omitted.\n * @returns One result per appended command.\n */\n run(options?: { timeout?: number }): Promise<GpioSequenceReport<Names>> {\n if (this.tail === undefined) {\n throw new Error('Sequence is empty');\n }\n\n const commands: GpioSequenceCommand[] = [];\n commands.length = this.tail.length;\n const associations: SequenceAssociation[] = [];\n for (let node: SequenceNode | undefined = this.tail; node; node = node.previous) {\n const index = node.length - 1;\n commands[index] = node.command;\n if (node.name !== undefined) {\n associations.push({ name: node.name, index, command: node.command });\n }\n }\n associations.reverse();\n const timeout = options?.timeout ?? 30;\n return this\n .fetch('/gpio/sequence', {\n method: 'POST',\n body: v.parse(sequenceRequest, { timeout, commands }),\n schema: v.pipe(\n sequenceReport,\n v.check((report) => matchesSequence(report, commands), 'Invalid GPIO sequence response'),\n ),\n // The shared client aborts after one second, which every sequence longer than\n // that would hit before the device answered.\n timeout: (timeout + 2) * 1000,\n })\n .then((wire) => new GpioSequenceReport<Names>(wire, associations));\n }\n\n // The pin list of a command that accepts either form, validated the way the device\n // validates it: at least one pin, each in range, each listed at most once.\n private pinList(method: 'read' | 'write', io: number | readonly number[]): readonly number[] {\n const pins = typeof io === 'number' ? [io] : io;\n if (pins.length === 0) {\n throw new Error(`${method}() needs at least one pin`);\n }\n for (const pin of pins) {\n this.check(pin);\n if (pins.indexOf(pin) !== pins.lastIndexOf(pin)) {\n throw new Error(`${method}() lists pin ${pin} twice`);\n }\n }\n\n return pins;\n }\n\n private check(io: number): void {\n if (io < 0 || io >= this.count) {\n throw new Error(\n `Invalid GPIO pin ${io} (RESOURCE_NOT_FOUND)\\n Suggestion: Use a pin number between 0 and ${\n this.count - 1\n }\\n Path: /gpio/sequence`,\n );\n }\n }\n\n private append<Descriptor extends SequenceDescriptor>(\n command: unknown,\n ): GpioSequence<Names, Descriptor> {\n if ((this.tail?.length ?? 0) >= 65536) throw new Error('Sequence exceeds 65536 commands');\n return new GpioSequence(this.fetch, this.count, {\n command: v.parse(sequenceCommand, command),\n previous: this.tail,\n length: (this.tail?.length ?? 0) + 1,\n });\n }\n}\n\n// Only the options the caller set: an omitted option must not reach the wire, so the\n// device sees the plain shape of a bare wait.\nconst waitFields = (options?: GpioSequenceWaitOptions) => ({\n ...(options?.timeout === undefined ? {} : { timeout: options.timeout }),\n ...(options?.stable_for === undefined ? {} : { stable_for: options.stable_for }),\n});\n\n// The wire carries the level as a string; a boolean is caller sugar.\nconst wireLevel = (level: GpioSequenceLevel) =>\n typeof level === 'boolean' ? (level ? 'high' : 'low') : level;\n"],"mappings":"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"}
package/build/gpio.d.cts CHANGED
@@ -1,3 +1,3 @@
1
1
  import { t as AnalogOutputLevel } from "./common-Cv6nZZS9.cjs";
2
- import { C as openDrainConfiguration, S as gpioConfiguration, _ as analogOutputConfiguration, a as DigitalInputConfiguration, b as digitalOutputConfiguration, c as GpioConfiguration, d as PartialDigitalInputConfiguration, f as PartialDigitalOutputConfiguration, g as analogInputConfiguration, h as SyncState, i as DigitalIO, l as OpenDrainConfiguration, m as SyncConfiguration, n as AnalogInputConfiguration, o as DigitalOutputConfiguration, p as PartialOpenDrainConfiguration, r as AnalogOutputConfiguration, s as GpioApi, t as AnalogIO, u as PartialAnalogOutputConfiguration, v as analogState, w as syncState, x as digitalState, y as digitalInputConfiguration } from "./gpio-CsxbjhA_.cjs";
3
- export { AnalogIO, AnalogInputConfiguration, AnalogOutputConfiguration, type AnalogOutputLevel, DigitalIO, DigitalInputConfiguration, DigitalOutputConfiguration, GpioApi, GpioConfiguration, OpenDrainConfiguration, PartialAnalogOutputConfiguration, PartialDigitalInputConfiguration, PartialDigitalOutputConfiguration, PartialOpenDrainConfiguration, SyncConfiguration, SyncState, analogInputConfiguration, analogOutputConfiguration, analogState, digitalInputConfiguration, digitalOutputConfiguration, digitalState, gpioConfiguration, openDrainConfiguration, syncState };
2
+ import { A as analogState, C as PartialDigitalInputConfiguration, D as SyncState, E as SyncConfiguration, F as openDrainConfiguration, I as syncState, M as digitalOutputConfiguration, N as digitalState, O as analogInputConfiguration, P as gpioConfiguration, S as PartialAnalogOutputConfiguration, T as PartialOpenDrainConfiguration, _ as GpioSequenceStep, a as DigitalInputConfiguration, b as GpioSequenceWaitVoltageOptions, c as GpioConfiguration, d as GpioSequenceExpectation, f as GpioSequenceLevel, g as GpioSequenceSample, h as GpioSequenceReport, i as DigitalIO, j as digitalInputConfiguration, k as analogOutputConfiguration, l as GpioSequence, m as GpioSequenceReadOptions, n as AnalogInputConfiguration, o as DigitalOutputConfiguration, p as GpioSequenceNamedResult, r as AnalogOutputConfiguration, s as GpioApi, t as AnalogIO, u as GpioSequenceCommand, v as GpioSequenceValue, w as PartialDigitalOutputConfiguration, x as OpenDrainConfiguration, y as GpioSequenceWaitOptions } from "./gpio-D3QEeLKh.cjs";
3
+ export { AnalogIO, AnalogInputConfiguration, AnalogOutputConfiguration, type AnalogOutputLevel, DigitalIO, DigitalInputConfiguration, DigitalOutputConfiguration, GpioApi, GpioConfiguration, GpioSequence, GpioSequenceCommand, GpioSequenceExpectation, GpioSequenceLevel, GpioSequenceNamedResult, GpioSequenceReadOptions, GpioSequenceReport, GpioSequenceSample, GpioSequenceStep, GpioSequenceValue, GpioSequenceWaitOptions, GpioSequenceWaitVoltageOptions, OpenDrainConfiguration, PartialAnalogOutputConfiguration, PartialDigitalInputConfiguration, PartialDigitalOutputConfiguration, PartialOpenDrainConfiguration, SyncConfiguration, SyncState, analogInputConfiguration, analogOutputConfiguration, analogState, digitalInputConfiguration, digitalOutputConfiguration, digitalState, gpioConfiguration, openDrainConfiguration, syncState };
package/build/gpio.d.mts CHANGED
@@ -1,3 +1,3 @@
1
1
  import { t as AnalogOutputLevel } from "./common-Cv6nZZS9.mjs";
2
- import { C as openDrainConfiguration, S as gpioConfiguration, _ as analogOutputConfiguration, a as DigitalInputConfiguration, b as digitalOutputConfiguration, c as GpioConfiguration, d as PartialDigitalInputConfiguration, f as PartialDigitalOutputConfiguration, g as analogInputConfiguration, h as SyncState, i as DigitalIO, l as OpenDrainConfiguration, m as SyncConfiguration, n as AnalogInputConfiguration, o as DigitalOutputConfiguration, p as PartialOpenDrainConfiguration, r as AnalogOutputConfiguration, s as GpioApi, t as AnalogIO, u as PartialAnalogOutputConfiguration, v as analogState, w as syncState, x as digitalState, y as digitalInputConfiguration } from "./gpio-Dk-s_yMc.mjs";
3
- export { AnalogIO, AnalogInputConfiguration, AnalogOutputConfiguration, type AnalogOutputLevel, DigitalIO, DigitalInputConfiguration, DigitalOutputConfiguration, GpioApi, GpioConfiguration, OpenDrainConfiguration, PartialAnalogOutputConfiguration, PartialDigitalInputConfiguration, PartialDigitalOutputConfiguration, PartialOpenDrainConfiguration, SyncConfiguration, SyncState, analogInputConfiguration, analogOutputConfiguration, analogState, digitalInputConfiguration, digitalOutputConfiguration, digitalState, gpioConfiguration, openDrainConfiguration, syncState };
2
+ import { A as analogState, C as PartialDigitalInputConfiguration, D as SyncState, E as SyncConfiguration, F as openDrainConfiguration, I as syncState, M as digitalOutputConfiguration, N as digitalState, O as analogInputConfiguration, P as gpioConfiguration, S as PartialAnalogOutputConfiguration, T as PartialOpenDrainConfiguration, _ as GpioSequenceStep, a as DigitalInputConfiguration, b as GpioSequenceWaitVoltageOptions, c as GpioConfiguration, d as GpioSequenceExpectation, f as GpioSequenceLevel, g as GpioSequenceSample, h as GpioSequenceReport, i as DigitalIO, j as digitalInputConfiguration, k as analogOutputConfiguration, l as GpioSequence, m as GpioSequenceReadOptions, n as AnalogInputConfiguration, o as DigitalOutputConfiguration, p as GpioSequenceNamedResult, r as AnalogOutputConfiguration, s as GpioApi, t as AnalogIO, u as GpioSequenceCommand, v as GpioSequenceValue, w as PartialDigitalOutputConfiguration, x as OpenDrainConfiguration, y as GpioSequenceWaitOptions } from "./gpio-5-tRkdTW.mjs";
3
+ export { AnalogIO, AnalogInputConfiguration, AnalogOutputConfiguration, type AnalogOutputLevel, DigitalIO, DigitalInputConfiguration, DigitalOutputConfiguration, GpioApi, GpioConfiguration, GpioSequence, GpioSequenceCommand, GpioSequenceExpectation, GpioSequenceLevel, GpioSequenceNamedResult, GpioSequenceReadOptions, GpioSequenceReport, GpioSequenceSample, GpioSequenceStep, GpioSequenceValue, GpioSequenceWaitOptions, GpioSequenceWaitVoltageOptions, OpenDrainConfiguration, PartialAnalogOutputConfiguration, PartialDigitalInputConfiguration, PartialDigitalOutputConfiguration, PartialOpenDrainConfiguration, SyncConfiguration, SyncState, analogInputConfiguration, analogOutputConfiguration, analogState, digitalInputConfiguration, digitalOutputConfiguration, digitalState, gpioConfiguration, openDrainConfiguration, syncState };
package/build/gpio.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import{n as e,r as t,t as n}from"./common-Ce3FeF-Q.mjs";import*as r from"valibot";const i=r.picklist([`release`,`hold`],`Invalid sync action`),a=r.object({mode:r.literal(`analog`),direction:r.literal(`input`)}),o=r.object({mode:r.literal(`analog`),direction:r.literal(`output`),value:r.optional(e)}),s=r.object({mode:r.literal(`digital`),direction:r.literal(`input`),vil:n,vih:n}),c=r.object({mode:r.literal(`digital`),direction:r.literal(`output`),value:t,vol:e,voh:e,vil:n,vih:n}),l=r.object({mode:r.literal(`digital`),direction:r.literal(`open_drain`),value:t,vil:n,vih:n});r.omit(o,[`direction`,`mode`]),r.omit(s,[`direction`,`mode`]);const u=r.partial(r.omit(c,[`direction`,`mode`]),[`vih`,`vil`]);r.omit(l,[`direction`,`mode`]);const d=r.object({value:t}),f=r.object({value:n}),p=r.object({action:i}),m=r.object({hold_state:r.picklist([`held`,`released`])}),h=r.union([c,l,s,o,a]);var g=class{fetch;count;constructor(e,t){this.fetch=e,this.count=t.capabilities.io.count}reset(){return this.fetch(`/gpio/reset`,{method:`POST`,parseResponse:()=>{}})}digital(e){if(e<0||e>=this.count)throw Error(`Invalid GPIO pin ${e} (RESOURCE_NOT_FOUND)\n Suggestion: Use a pin number between 0 and ${this.count-1}\n Path: /gpio/${e}`);return new _(this.fetch,e)}analog(e){if(e<0||e>=this.count)throw Error(`Invalid GPIO pin ${e} (RESOURCE_NOT_FOUND)\n Suggestion: Use a pin number between 0 and ${this.count-1}\n Path: /gpio/${e}`);return new v(this.fetch,e)}hold(){return this.fetch(`/gpio/sync`,{method:`POST`,body:{action:`hold`},schema:p})}release(){return this.fetch(`/gpio/sync`,{method:`POST`,body:{action:`release`},schema:p})}read_config(e){if(e<0||e>=this.count)throw Error(`Invalid GPIO pin ${e} (RESOURCE_NOT_FOUND)\n Suggestion: Use a pin number between 0 and ${this.count-1}\n Path: /gpio/${e}/config`);return this.fetch(`/gpio/${e}/config`,{schema:h})}read_sync(){return this.fetch(`/gpio/sync`,{schema:m})}},_=class{fetch;id;constructor(e,t){this.fetch=e,this.id=t}configure_input(e){return this.fetch(`/gpio/${this.id}/config`,{method:`PATCH`,body:r.parse(s,{...e,mode:`digital`,direction:`input`}),schema:s})}configure_output(e){e=r.parse(u,e);let t={mode:`digital`,direction:`output`,value:e.value,vol:e.vol,voh:e.voh,vil:e.vil??e.vol+(e.voh-e.vol)/4,vih:e.vih??e.voh-(e.voh-e.vol)/4};return this.fetch(`/gpio/${this.id}/config`,{method:`PATCH`,body:r.parse(c,t),schema:c})}async read(){return(await this.fetch(`/gpio/${this.id}/state`,{schema:d})).value}async write(e){return(await this.fetch(`/gpio/${this.id}/state`,{method:`PUT`,body:r.parse(d,{value:e}),schema:d})).value}configure_open_drain(e){return this.fetch(`/gpio/${this.id}/config`,{method:`PATCH`,body:r.parse(l,{...e,mode:`digital`,direction:`open_drain`}),schema:l})}},v=class{fetch;id;constructor(e,t){this.fetch=e,this.id=t}configure_input(){return this.fetch(`/gpio/${this.id}/config`,{method:`PATCH`,body:{mode:`analog`,direction:`input`},schema:a})}configure_output(e){return this.fetch(`/gpio/${this.id}/config`,{method:`PATCH`,body:r.parse(o,{value:e,mode:`analog`,direction:`output`}),schema:o})}async read(){return(await this.fetch(`/gpio/${this.id}/state`,{schema:f})).value}async write(e){return(await this.fetch(`/gpio/${this.id}/state`,{method:`PUT`,body:{value:e},schema:f})).value}};export{v as AnalogIO,_ as DigitalIO,g as GpioApi,a as analogInputConfiguration,o as analogOutputConfiguration,f as analogState,s as digitalInputConfiguration,c as digitalOutputConfiguration,d as digitalState,h as gpioConfiguration,l as openDrainConfiguration,m as syncState};
1
+ import{n as e,r as t,t as n}from"./common-Ce3FeF-Q.mjs";import*as r from"valibot";const i=r.picklist([`release`,`hold`],`Invalid sync action`),a=r.object({mode:r.literal(`analog`),direction:r.literal(`input`)}),o=r.object({mode:r.literal(`analog`),direction:r.literal(`output`),value:r.optional(e)}),s=r.object({mode:r.literal(`digital`),direction:r.literal(`input`),vil:n,vih:n}),c=r.object({mode:r.literal(`digital`),direction:r.literal(`output`),value:t,vol:e,voh:e,vil:n,vih:n}),l=r.object({mode:r.literal(`digital`),direction:r.literal(`open_drain`),value:t,vil:n,vih:n});r.omit(o,[`direction`,`mode`]),r.omit(s,[`direction`,`mode`]);const u=r.partial(r.omit(c,[`direction`,`mode`]),[`vih`,`vil`]);r.omit(l,[`direction`,`mode`]);const d=r.object({value:t}),f=r.object({value:n}),p=r.object({action:i}),m=r.object({hold_state:r.picklist([`held`,`released`])}),h=r.picklist([`read`,`write`,`wait_voltage`,`wait_level`,`delay`,`hold`,`release`]),g=r.pipe(r.number(),r.finite(),r.minValue(Number.MIN_VALUE)),_=r.pipe(r.number(),r.integer(),r.minValue(0),r.maxValue(31)),v=r.union([_,r.pipe(r.array(_),r.minLength(1))]),y=r.union([r.boolean(),e]),b=r.union([y,r.pipe(r.array(y),r.minLength(1))]),x=r.pipe(r.number(),r.integer(),r.minValue(1)),S=r.object({min:n,max:n}),C=r.picklist([`low`,`high`],`Invalid level`),w=r.union([r.boolean(),S]),T=r.variant(`op`,[r.object({op:r.literal(`read`),io:v,repeat:r.optional(x),delay:r.optional(g),expect:r.optional(w)}),r.object({op:r.literal(`write`),io:v,value:b}),r.object({op:r.literal(`wait_voltage`),io:_,min:r.optional(n),max:r.optional(n),timeout:r.optional(g),stable_for:r.optional(g)}),r.object({op:r.literal(`wait_level`),io:_,level:C,timeout:r.optional(g),stable_for:r.optional(g)}),r.object({op:r.literal(`delay`),duration:g}),r.object({op:r.literal(`hold`)}),r.object({op:r.literal(`release`)})]),E=r.object({timeout:g,commands:r.pipe(r.array(T),r.minLength(1),r.maxLength(65536))}),D=r.object({io:r.number(),value:r.union([r.boolean(),r.number()]),elapsed:r.number()}),O=r.object({op:h,io:r.optional(r.union([r.number(),r.array(r.number())])),value:r.optional(r.union([r.boolean(),r.number()])),samples:r.optional(r.array(D)),elapsed:r.number()}),k=r.object({elapsed:r.number(),results:r.array(O)});var A=class{elapsed;results;named;#e;constructor(e,t=[]){this.elapsed=e.elapsed,this.results=e.results;let n=Object.create(null);for(let r of t){let t=N(r,e.results[r.index]);n[r.name]=t}this.named=Object.freeze(n),this.#e=n}get(e){return this.#e[e]}toJSON(){return{elapsed:this.elapsed,results:this.results}}};const j=e=>{switch(e.op){case`read`:return Array.isArray(e.io)||(e.repeat??1)>1?`collection`:`scalar`;case`write`:return Array.isArray(e.io)&&e.io.length>1?`collection`:`scalar`;case`wait_voltage`:case`wait_level`:return`scalar`;default:return`control`}},M=(e,t)=>e.results.length===t.length&&e.results.every((e,n)=>{let r=t[n];if(e.op!==r.op)return!1;let i=`io`in r?r.io:void 0;if(Array.isArray(i)){if(!Array.isArray(e.io)||i.length!==e.io.length||!i.every((t,n)=>t===e.io[n]))return!1}else if(e.io!==i)return!1;let a=j(r);if(a===`control`)return e.value===void 0&&e.samples===void 0;if(a===`scalar`)return e.samples===void 0&&e.value!==void 0;let o=Array.isArray(i)?i:[i],s=o.length*(r.op===`read`?r.repeat??1:1);if(r.op===`read`&&s===1&&e.value!==void 0&&e.samples===void 0)return!0;if(e.value!==void 0)return!1;let c=e.samples??[];return c.length===s&&c.every((e,t)=>e.io===o[t%o.length])}),N=({name:e,index:t,command:n},r)=>{let i={name:e,index:t,op:n.op,elapsed:r.elapsed};switch(j(n)){case`scalar`:return{...i,kind:`scalar`,io:r.io,value:r.value};case`collection`:return{...i,kind:`collection`,io:r.io,samples:r.samples??[{io:r.io[0],value:r.value,elapsed:r.elapsed}]};default:return{...i,kind:`control`}}},P=r.union([c,l,s,o,a]);var F=class{fetch;count;constructor(e,t){this.fetch=e,this.count=t.capabilities.io.count}reset(){return this.fetch(`/gpio/reset`,{method:`POST`,parseResponse:()=>{}})}digital(e){if(e<0||e>=this.count)throw Error(`Invalid GPIO pin ${e} (RESOURCE_NOT_FOUND)\n Suggestion: Use a pin number between 0 and ${this.count-1}\n Path: /gpio/${e}`);return new I(this.fetch,e)}analog(e){if(e<0||e>=this.count)throw Error(`Invalid GPIO pin ${e} (RESOURCE_NOT_FOUND)\n Suggestion: Use a pin number between 0 and ${this.count-1}\n Path: /gpio/${e}`);return new L(this.fetch,e)}hold(){return this.fetch(`/gpio/sync`,{method:`POST`,body:{action:`hold`},schema:p})}release(){return this.fetch(`/gpio/sync`,{method:`POST`,body:{action:`release`},schema:p})}read_config(e){if(e<0||e>=this.count)throw Error(`Invalid GPIO pin ${e} (RESOURCE_NOT_FOUND)\n Suggestion: Use a pin number between 0 and ${this.count-1}\n Path: /gpio/${e}/config`);return this.fetch(`/gpio/${e}/config`,{schema:P})}read_sync(){return this.fetch(`/gpio/sync`,{schema:m})}sequence(){return new R(this.fetch,this.count)}},I=class{fetch;id;constructor(e,t){this.fetch=e,this.id=t}configure_input(e){return this.fetch(`/gpio/${this.id}/config`,{method:`PATCH`,body:r.parse(s,{...e,mode:`digital`,direction:`input`}),schema:s})}configure_output(e){e=r.parse(u,e);let t={mode:`digital`,direction:`output`,value:e.value,vol:e.vol,voh:e.voh,vil:e.vil??e.vol+(e.voh-e.vol)/4,vih:e.vih??e.voh-(e.voh-e.vol)/4};return this.fetch(`/gpio/${this.id}/config`,{method:`PATCH`,body:r.parse(c,t),schema:c})}async read(){return(await this.fetch(`/gpio/${this.id}/state`,{schema:d})).value}async write(e){return(await this.fetch(`/gpio/${this.id}/state`,{method:`PUT`,body:r.parse(d,{value:e}),schema:d})).value}configure_open_drain(e){return this.fetch(`/gpio/${this.id}/config`,{method:`PATCH`,body:r.parse(l,{...e,mode:`digital`,direction:`open_drain`}),schema:l})}},L=class{fetch;id;constructor(e,t){this.fetch=e,this.id=t}configure_input(){return this.fetch(`/gpio/${this.id}/config`,{method:`PATCH`,body:{mode:`analog`,direction:`input`},schema:a})}configure_output(e){return this.fetch(`/gpio/${this.id}/config`,{method:`PATCH`,body:r.parse(o,{value:e,mode:`analog`,direction:`output`}),schema:o})}async read(){return(await this.fetch(`/gpio/${this.id}/state`,{schema:f})).value}async write(e){return(await this.fetch(`/gpio/${this.id}/state`,{method:`PUT`,body:{value:e},schema:f})).value}},R=class e{fetch;count;tail;constructor(e,t,n){this.fetch=e,this.count=t,this.tail=n}read(e,t){if(this.pinList(`read`,e),t?.delay!==void 0&&(t.repeat??1)<2)throw Error(`read() delay needs repeat of 2 or more`);return this.append({op:`read`,io:e,...t?.repeat===void 0?{}:{repeat:t.repeat},...t?.delay===void 0?{}:{delay:t.delay},...t?.expect===void 0?{}:{expect:t.expect}})}write(e,t){let n=this.pinList(`write`,e);if(Array.isArray(t)&&t.length!==n.length)throw Error(`write() got ${t.length} values for ${n.length} pins`);return this.append({op:`write`,io:e,value:t})}wait_voltage(e,t){this.check(e);let{min:n,max:r}=t;if(n===void 0&&r===void 0)throw Error(`wait_voltage() needs min, max, or both`);if(n!==void 0&&r!==void 0&&n>r)throw Error(`wait_voltage() min ${n} is above max ${r}`);return this.append({op:`wait_voltage`,io:e,...n===void 0?{}:{min:n},...r===void 0?{}:{max:r},...z(t)})}wait_level(e,t,n){return this.check(e),this.append({op:`wait_level`,io:e,level:B(t),...z(n)})}delay(e){return this.append({op:`delay`,duration:e})}hold(){return this.append({op:`hold`})}release(){return this.append({op:`release`})}as(t){if(typeof t!=`string`||t.length===0)throw Error(`Sequence name must be a nonempty string`);if(this.tail===void 0)throw Error(`No sequence command to name`);if(this.tail.name!==void 0)throw Error(`Sequence command is already named`);for(let e=this.tail;e;e=e.previous)if(e.name===t)throw Error(`Duplicate sequence name: ${t}`);return new e(this.fetch,this.count,{...this.tail,name:t})}run(e){if(this.tail===void 0)throw Error(`Sequence is empty`);let t=[];t.length=this.tail.length;let n=[];for(let e=this.tail;e;e=e.previous){let r=e.length-1;t[r]=e.command,e.name!==void 0&&n.push({name:e.name,index:r,command:e.command})}n.reverse();let i=e?.timeout??30;return this.fetch(`/gpio/sequence`,{method:`POST`,body:r.parse(E,{timeout:i,commands:t}),schema:r.pipe(k,r.check(e=>M(e,t),`Invalid GPIO sequence response`)),timeout:(i+2)*1e3}).then(e=>new A(e,n))}pinList(e,t){let n=typeof t==`number`?[t]:t;if(n.length===0)throw Error(`${e}() needs at least one pin`);for(let t of n)if(this.check(t),n.indexOf(t)!==n.lastIndexOf(t))throw Error(`${e}() lists pin ${t} twice`);return n}check(e){if(e<0||e>=this.count)throw Error(`Invalid GPIO pin ${e} (RESOURCE_NOT_FOUND)\n Suggestion: Use a pin number between 0 and ${this.count-1}\n Path: /gpio/sequence`)}append(t){if((this.tail?.length??0)>=65536)throw Error(`Sequence exceeds 65536 commands`);return new e(this.fetch,this.count,{command:r.parse(T,t),previous:this.tail,length:(this.tail?.length??0)+1})}};const z=e=>({...e?.timeout===void 0?{}:{timeout:e.timeout},...e?.stable_for===void 0?{}:{stable_for:e.stable_for}}),B=e=>typeof e==`boolean`?e?`high`:`low`:e;export{L as AnalogIO,I as DigitalIO,F as GpioApi,R as GpioSequence,A as GpioSequenceReport,a as analogInputConfiguration,o as analogOutputConfiguration,f as analogState,s as digitalInputConfiguration,c as digitalOutputConfiguration,d as digitalState,P as gpioConfiguration,l as openDrainConfiguration,m as syncState};
2
2
  //# sourceMappingURL=gpio.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"gpio.mjs","names":[],"sources":["../src/api/gpio.ts"],"sourcesContent":["import type { UpFetch } from 'up-fetch';\nimport * as v from 'valibot';\n\nimport { analogLevel, type AnalogOutputLevel, analogOutputLevel, digitalLevel } from './common';\nimport type { Information } from './management';\n\nexport type { AnalogOutputLevel };\n\nconst syncAction = v.picklist(['release', 'hold'], 'Invalid sync action');\nexport const analogInputConfiguration = v.object({\n mode: v.literal('analog'),\n direction: v.literal('input'),\n});\nexport const analogOutputConfiguration = v.object({\n mode: v.literal('analog'),\n direction: v.literal('output'),\n value: v.optional(analogOutputLevel),\n});\nexport const digitalInputConfiguration = v.object({\n mode: v.literal('digital'),\n direction: v.literal('input'),\n vil: analogLevel,\n vih: analogLevel,\n});\nexport const digitalOutputConfiguration = v.object({\n mode: v.literal('digital'),\n direction: v.literal('output'),\n value: digitalLevel,\n vol: analogOutputLevel,\n voh: analogOutputLevel,\n vil: analogLevel,\n vih: analogLevel,\n});\nexport const openDrainConfiguration = v.object({\n mode: v.literal('digital'),\n direction: v.literal('open_drain'),\n value: digitalLevel,\n vil: analogLevel,\n vih: analogLevel,\n});\nexport type AnalogInputConfiguration = v.InferOutput<typeof analogInputConfiguration>;\nexport type AnalogOutputConfiguration = v.InferOutput<typeof analogOutputConfiguration>;\nexport type DigitalInputConfiguration = v.InferOutput<typeof digitalInputConfiguration>;\nexport type DigitalOutputConfiguration = v.InferOutput<typeof digitalOutputConfiguration>;\nexport type OpenDrainConfiguration = v.InferOutput<typeof openDrainConfiguration>;\n\nconst partialAnalogOutputConfiguration = v.omit(analogOutputConfiguration, ['direction', 'mode']);\nexport type PartialAnalogOutputConfiguration = v.InferOutput<\n typeof partialAnalogOutputConfiguration\n>;\nconst partialDigitalInputConfiguration = v.omit(digitalInputConfiguration, ['direction', 'mode']);\nexport type PartialDigitalInputConfiguration = v.InferOutput<\n typeof partialDigitalInputConfiguration\n>;\nconst partialDigitalOutputConfiguration = v.partial(\n v.omit(digitalOutputConfiguration, ['direction', 'mode']),\n ['vih', 'vil'],\n);\nexport type PartialDigitalOutputConfiguration = v.InferInput<\n typeof partialDigitalOutputConfiguration\n>;\nconst partialOpenDrainConfiguration = v.omit(openDrainConfiguration, ['direction', 'mode']);\nexport type PartialOpenDrainConfiguration = v.InferOutput<typeof partialOpenDrainConfiguration>;\n\nexport const digitalState = v.object({ value: digitalLevel });\nexport const analogState = v.object({ value: analogLevel });\n\nconst syncConfiguration = v.object({ action: syncAction });\nexport type SyncConfiguration = v.InferOutput<typeof syncConfiguration>;\n\nexport const syncState = v.object({ hold_state: v.picklist(['held', 'released']) });\nexport type SyncState = v.InferOutput<typeof syncState>;\n\nexport const gpioConfiguration = v.union([\n digitalOutputConfiguration,\n openDrainConfiguration,\n digitalInputConfiguration,\n analogOutputConfiguration,\n analogInputConfiguration,\n]);\nexport type GpioConfiguration = v.InferOutput<typeof gpioConfiguration>;\n\n/** @hideconstructor */\nexport class GpioApi {\n private count: number;\n\n constructor(private readonly fetch: UpFetch, info: Information) {\n this.count = info.capabilities.io.count;\n }\n\n /**\n * Resets all IO configurations to default.\n */\n reset(): Promise<void> {\n return this.fetch('/gpio/reset', { method: 'POST', parseResponse: () => {} });\n }\n\n /**\n * Access a specific digital IO pin by id.\n * @param io The IO pin id.\n * @returns The digital IO instance.\n */\n digital(io: number): DigitalIO {\n if (io < 0 || io >= this.count) {\n throw new Error(\n `Invalid GPIO pin ${io} (RESOURCE_NOT_FOUND)\\n Suggestion: Use a pin number between 0 and ${\n this.count - 1\n }\\n Path: /gpio/${io}`,\n );\n }\n\n return new DigitalIO(this.fetch, io);\n }\n\n /**\n * Access a specific analog IO pin by id.\n * @param io The IO pin id.\n * @returns The analog IO instance.\n */\n analog(io: number): AnalogIO {\n if (io < 0 || io >= this.count) {\n throw new Error(\n `Invalid GPIO pin ${io} (RESOURCE_NOT_FOUND)\\n Suggestion: Use a pin number between 0 and ${\n this.count - 1\n }\\n Path: /gpio/${io}`,\n );\n }\n\n return new AnalogIO(this.fetch, io);\n }\n\n /**\n * Holds the current state of all GPIO pins.\n * @returns The applied sync state.\n */\n hold(): Promise<SyncConfiguration> {\n return this.fetch('/gpio/sync', {\n method: 'POST',\n body: { action: 'hold' } satisfies SyncConfiguration,\n schema: syncConfiguration,\n });\n }\n\n /**\n * Releases control of the IO pins, allowing external control.\n *\n * This also sets the device as a slave.\n *\n * @returns The applied sync state.\n */\n release(): Promise<SyncConfiguration> {\n return this.fetch('/gpio/sync', {\n method: 'POST',\n body: { action: 'release' } satisfies SyncConfiguration,\n schema: syncConfiguration,\n });\n }\n\n /**\n * Reads back the current configuration of a specific IO pin.\n * @param io The IO pin id.\n * @returns The pin's current configuration.\n */\n read_config(io: number): Promise<GpioConfiguration> {\n if (io < 0 || io >= this.count) {\n throw new Error(\n `Invalid GPIO pin ${io} (RESOURCE_NOT_FOUND)\\n Suggestion: Use a pin number between 0 and ${\n this.count - 1\n }\\n Path: /gpio/${io}/config`,\n );\n }\n\n return this.fetch(`/gpio/${io}/config`, { schema: gpioConfiguration });\n }\n\n /**\n * Reads the current hold state of all GPIO pins.\n * @returns The current sync state.\n */\n read_sync(): Promise<SyncState> {\n return this.fetch('/gpio/sync', { schema: syncState });\n }\n}\n\n/** @hideconstructor */\nexport class DigitalIO {\n constructor(private readonly fetch: UpFetch, public readonly id: number) {}\n\n /**\n * Configure the pin as a digital input.\n * @param config The digital input configuration.\n * @returns The applied configuration.\n */\n configure_input(config: PartialDigitalInputConfiguration): Promise<DigitalInputConfiguration> {\n return this.fetch(`/gpio/${this.id}/config`, {\n method: 'PATCH',\n body: v.parse(\n digitalInputConfiguration,\n { ...config, mode: 'digital', direction: 'input' } satisfies DigitalInputConfiguration,\n ),\n schema: digitalInputConfiguration,\n });\n }\n\n /**\n * Configures the pin as a digital output.\n * @param config The digital output configuration.\n * @returns The applied configuration.\n */\n configure_output(config: PartialDigitalOutputConfiguration): Promise<DigitalOutputConfiguration> {\n config = v.parse(partialDigitalOutputConfiguration, config);\n\n const fullConfig = {\n mode: 'digital' as const,\n direction: 'output' as const,\n value: config.value,\n vol: config.vol,\n voh: config.voh,\n vil: config.vil ?? config.vol + (config.voh - config.vol) / 4,\n vih: config.vih ?? config.voh - (config.voh - config.vol) / 4,\n };\n\n return this.fetch(`/gpio/${this.id}/config`, {\n method: 'PATCH',\n body: v.parse(digitalOutputConfiguration, fullConfig),\n schema: digitalOutputConfiguration,\n });\n }\n\n /**\n * Reads the current state of the pin.\n * @returns The current state of the pin.\n */\n async read(): Promise<boolean> {\n return (await this.fetch(`/gpio/${this.id}/state`, { schema: digitalState })).value;\n }\n\n /**\n * Writes a value to the pin.\n * @param value The value to write.\n * @returns The written value.\n */\n async write(value: boolean | number): Promise<boolean> {\n return (await this.fetch(`/gpio/${this.id}/state`, {\n method: 'PUT',\n body: v.parse(digitalState, { value }),\n schema: digitalState,\n }))\n .value;\n }\n\n /**\n * Configure the pin as an open drain output.\n * @param config The open drain configuration.\n * @returns The applied configuration.\n */\n configure_open_drain(config: PartialOpenDrainConfiguration): Promise<OpenDrainConfiguration> {\n return this.fetch(`/gpio/${this.id}/config`, {\n method: 'PATCH',\n body: v.parse(\n openDrainConfiguration,\n { ...config, mode: 'digital', direction: 'open_drain' } satisfies OpenDrainConfiguration,\n ),\n schema: openDrainConfiguration,\n });\n }\n}\n\n/** @hideconstructor */\nexport class AnalogIO {\n constructor(private readonly fetch: UpFetch, public readonly id: number) {}\n\n /**\n * Configures the pin as an analog input.\n * @returns The applied configuration.\n * @returns The applied configuration.\n */\n configure_input(): Promise<AnalogInputConfiguration> {\n return this.fetch(`/gpio/${this.id}/config`, {\n method: 'PATCH',\n body: { mode: 'analog', direction: 'input' } satisfies AnalogInputConfiguration,\n schema: analogInputConfiguration,\n });\n }\n\n /**\n * Configures the pin as an analog output.\n * @param config The analog output configuration.\n * @returns The applied configuration.\n */\n configure_output(value: AnalogOutputLevel): Promise<AnalogOutputConfiguration> {\n return this.fetch(`/gpio/${this.id}/config`, {\n method: 'PATCH',\n body: v.parse(\n analogOutputConfiguration,\n { value, mode: 'analog', direction: 'output' } satisfies AnalogOutputConfiguration,\n ),\n schema: analogOutputConfiguration,\n });\n }\n\n /**\n * Reads the current state of the pin.\n * @returns The current state of the pin.\n */\n async read(): Promise<number> {\n return (await this.fetch(`/gpio/${this.id}/state`, { schema: analogState })).value;\n }\n\n /**\n * Writes a value to the pin.\n * @param value The value to write.\n * @returns The written value.\n */\n async write(value: number): Promise<number> {\n return (await this.fetch(`/gpio/${this.id}/state`, {\n method: 'PUT',\n body: { value },\n schema: analogState,\n }))\n .value;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"gpio.mjs","names":[],"sources":["../src/api/gpio.ts"],"sourcesContent":["import type { UpFetch } from 'up-fetch';\nimport * as v from 'valibot';\n\nimport { type AnalogOutputLevel, analogLevel, analogOutputLevel, digitalLevel } from './common';\nimport type { Information } from './management';\n\nexport type { AnalogOutputLevel };\n\nconst syncAction = v.picklist(['release', 'hold'], 'Invalid sync action');\nexport const analogInputConfiguration = v.object({\n mode: v.literal('analog'),\n direction: v.literal('input'),\n});\nexport const analogOutputConfiguration = v.object({\n mode: v.literal('analog'),\n direction: v.literal('output'),\n value: v.optional(analogOutputLevel),\n});\n/**\n * Input thresholds `vil` and `vih` are in [-25, 25] V, inclusive.\n */\nexport const digitalInputConfiguration = v.object({\n mode: v.literal('digital'),\n direction: v.literal('input'),\n vil: analogLevel,\n vih: analogLevel,\n});\n/**\n * Readback thresholds `vil` and `vih` are in [-25, 25] V, inclusive.\n * Output levels `vol` and `voh` are in [0, 24] V, inclusive.\n */\nexport const digitalOutputConfiguration = v.object({\n mode: v.literal('digital'),\n direction: v.literal('output'),\n value: digitalLevel,\n vol: analogOutputLevel,\n voh: analogOutputLevel,\n vil: analogLevel,\n vih: analogLevel,\n});\n/**\n * Readback thresholds `vil` and `vih` are in [-25, 25] V, inclusive.\n */\nexport const openDrainConfiguration = v.object({\n mode: v.literal('digital'),\n direction: v.literal('open_drain'),\n value: digitalLevel,\n vil: analogLevel,\n vih: analogLevel,\n});\nexport type AnalogInputConfiguration = v.InferOutput<typeof analogInputConfiguration>;\nexport type AnalogOutputConfiguration = v.InferOutput<typeof analogOutputConfiguration>;\nexport type DigitalInputConfiguration = v.InferOutput<typeof digitalInputConfiguration>;\nexport type DigitalOutputConfiguration = v.InferOutput<typeof digitalOutputConfiguration>;\nexport type OpenDrainConfiguration = v.InferOutput<typeof openDrainConfiguration>;\n\nconst partialAnalogOutputConfiguration = v.omit(analogOutputConfiguration, ['direction', 'mode']);\nexport type PartialAnalogOutputConfiguration = v.InferOutput<\n typeof partialAnalogOutputConfiguration\n>;\nconst partialDigitalInputConfiguration = v.omit(digitalInputConfiguration, ['direction', 'mode']);\nexport type PartialDigitalInputConfiguration = v.InferOutput<\n typeof partialDigitalInputConfiguration\n>;\nconst partialDigitalOutputConfiguration = v.partial(\n v.omit(digitalOutputConfiguration, ['direction', 'mode']),\n ['vih', 'vil'],\n);\nexport type PartialDigitalOutputConfiguration = v.InferInput<\n typeof partialDigitalOutputConfiguration\n>;\nconst partialOpenDrainConfiguration = v.omit(openDrainConfiguration, ['direction', 'mode']);\nexport type PartialOpenDrainConfiguration = v.InferOutput<typeof partialOpenDrainConfiguration>;\n\nexport const digitalState = v.object({ value: digitalLevel });\nexport const analogState = v.object({ value: analogLevel });\n\nconst syncConfiguration = v.object({ action: syncAction });\nexport type SyncConfiguration = v.InferOutput<typeof syncConfiguration>;\n\nexport const syncState = v.object({ hold_state: v.picklist(['held', 'released']) });\nexport type SyncState = v.InferOutput<typeof syncState>;\n\nconst sequenceOp = v.picklist([\n 'read',\n 'write',\n 'wait_voltage',\n 'wait_level',\n 'delay',\n 'hold',\n 'release',\n]);\nconst sequenceDuration = v.pipe(v.number(), v.finite(), v.minValue(Number.MIN_VALUE));\nconst sequenceIo = v.pipe(v.number(), v.integer(), v.minValue(0), v.maxValue(31));\nconst sequencePins = v.union([sequenceIo, v.pipe(v.array(sequenceIo), v.minLength(1))]);\n// A digital level or a voltage: the device decides from the pin's configured mode.\n// Numbers stay in [0, 24] because the same field carries volts, so a numeric digital\n// level uses 0 for low and anything else for high.\nconst sequenceValue = v.union([v.boolean(), analogOutputLevel]);\n// One value for every listed pin, or one value per pin paired with the pin list.\nconst sequenceValues = v.union([sequenceValue, v.pipe(v.array(sequenceValue), v.minLength(1))]);\nconst sequenceRepeat = v.pipe(v.number(), v.integer(), v.minValue(1));\nconst sequenceBounds = v.object({ min: analogLevel, max: analogLevel });\nconst sequenceLevel = v.picklist(['low', 'high'], 'Invalid level');\nconst sequenceExpect = v.union([v.boolean(), sequenceBounds]);\nconst sequenceCommand = v.variant('op', [\n v.object({\n op: v.literal('read'),\n io: sequencePins,\n repeat: v.optional(sequenceRepeat),\n delay: v.optional(sequenceDuration),\n expect: v.optional(sequenceExpect),\n }),\n v.object({ op: v.literal('write'), io: sequencePins, value: sequenceValues }),\n v.object({\n op: v.literal('wait_voltage'),\n io: sequenceIo,\n min: v.optional(analogLevel),\n max: v.optional(analogLevel),\n timeout: v.optional(sequenceDuration),\n stable_for: v.optional(sequenceDuration),\n }),\n v.object({\n op: v.literal('wait_level'),\n io: sequenceIo,\n level: sequenceLevel,\n timeout: v.optional(sequenceDuration),\n stable_for: v.optional(sequenceDuration),\n }),\n v.object({ op: v.literal('delay'), duration: sequenceDuration }),\n v.object({ op: v.literal('hold') }),\n v.object({ op: v.literal('release') }),\n]);\nconst sequenceRequest = v.object({\n timeout: sequenceDuration,\n commands: v.pipe(v.array(sequenceCommand), v.minLength(1), v.maxLength(65536)),\n});\nconst sequenceSample = v.object({\n io: v.number(),\n value: v.union([v.boolean(), v.number()]),\n elapsed: v.number(),\n});\nconst sequenceStep = v.object({\n op: sequenceOp,\n io: v.optional(v.union([v.number(), v.array(v.number())])),\n value: v.optional(v.union([v.boolean(), v.number()])),\n samples: v.optional(v.array(sequenceSample)),\n elapsed: v.number(),\n});\nconst sequenceReport = v.object({ elapsed: v.number(), results: v.array(sequenceStep) });\n\nexport type GpioSequenceCommand = v.InferOutput<typeof sequenceCommand>;\nexport type GpioSequenceSample = v.InferOutput<typeof sequenceSample>;\n/**\n * Result of one command.\n *\n * `value` carries a single-valued step — an ordinary read of one pin with no repeat, or\n * a write of one pin — while `samples` carries a step that covered several pins or\n * repeated: the readings of a `read`, or the values a `write` applied.\n */\nexport type GpioSequenceStep = v.InferOutput<typeof sequenceStep>;\ntype SequenceWireReport = v.InferOutput<typeof sequenceReport>;\ntype SequenceKind = 'scalar' | 'collection' | 'control';\ntype SequenceDescriptor<\n Op extends GpioSequenceCommand['op'] = GpioSequenceCommand['op'],\n Kind extends SequenceKind = SequenceKind,\n> = { op: Op; kind: Kind };\ntype SequenceMetadata<Op> = { name: string; index: number; op: Op };\ntype SequenceAttempt<Op> = SequenceMetadata<Op> & { elapsed: number };\ntype SequenceScalar<Op> = SequenceAttempt<Op> & {\n kind: 'scalar';\n io: number | number[];\n value: boolean | number;\n};\ntype SequenceCollection<Op> = SequenceAttempt<Op> & {\n kind: 'collection';\n io: number | number[];\n samples: GpioSequenceSample[];\n};\ntype SequenceControl<Op> = SequenceAttempt<Op> & { kind: 'control' };\ntype SequenceResultForKind<Op, Kind> = Kind extends 'scalar' ? SequenceScalar<Op>\n : Kind extends 'collection' ? SequenceCollection<Op>\n : SequenceControl<Op>;\ntype SequenceResult<Descriptor> = Descriptor extends SequenceDescriptor<infer Op, infer Kind>\n ? SequenceResultForKind<Op, Kind>\n : never;\ntype SequenceDescriptors =\n | SequenceDescriptor<'read' | 'write', 'scalar' | 'collection'>\n | SequenceDescriptor<'wait_voltage' | 'wait_level', 'scalar'>\n | SequenceDescriptor<'hold' | 'release' | 'delay', 'control'>;\nexport type GpioSequenceNamedResult = SequenceResult<SequenceDescriptors>;\ntype SequenceNamed<Names> = { readonly [Name in keyof Names]: SequenceResult<Names[Name]> };\ntype SequenceAssociation = { name: string; index: number; command: GpioSequenceCommand };\n\n/** Raw results remain in command order. Names are local to this run. */\nexport class GpioSequenceReport<Names = {}> {\n readonly elapsed: number;\n readonly results: GpioSequenceStep[];\n readonly named: SequenceNamed<Names>;\n readonly #lookup: Readonly<Record<string, GpioSequenceNamedResult>>;\n\n /** Constructing a bare wire report does not restore command names. */\n constructor(wire: SequenceWireReport, associations: readonly SequenceAssociation[] = []) {\n this.elapsed = wire.elapsed;\n this.results = wire.results;\n const named: Record<string, GpioSequenceNamedResult> = Object.create(null);\n for (const association of associations) {\n const result = namedSequenceResult(association, wire.results[association.index]);\n named[association.name] = result;\n }\n this.named = Object.freeze(named) as SequenceNamed<Names>;\n this.#lookup = named;\n }\n\n get(name: string): GpioSequenceNamedResult | undefined {\n return this.#lookup[name];\n }\n\n toJSON(): SequenceWireReport {\n return { elapsed: this.elapsed, results: this.results };\n }\n}\n\nconst sequenceKind = (command: GpioSequenceCommand): SequenceKind => {\n switch (command.op) {\n case 'read':\n return Array.isArray(command.io) || (command.repeat ?? 1) > 1 ? 'collection' : 'scalar';\n case 'write':\n return Array.isArray(command.io) && command.io.length > 1 ? 'collection' : 'scalar';\n case 'wait_voltage':\n case 'wait_level':\n return 'scalar';\n default:\n return 'control';\n }\n};\n\nconst matchesSequence = (report: SequenceWireReport, commands: GpioSequenceCommand[]): boolean => {\n if (report.results.length !== commands.length) return false;\n return report.results.every((step, index) => {\n const command = commands[index];\n if (step.op !== command.op) return false;\n const io = 'io' in command ? command.io : undefined;\n if (Array.isArray(io)) {\n if (!Array.isArray(step.io) || io.length !== step.io.length) return false;\n if (!io.every((pin, offset) => pin === (step.io as number[])[offset])) return false;\n } else if (step.io !== io) {\n return false;\n }\n const kind = sequenceKind(command);\n if (kind === 'control') return step.value === undefined && step.samples === undefined;\n if (kind === 'scalar') return step.samples === undefined && step.value !== undefined;\n const pins = Array.isArray(io) ? io : [io];\n const count = pins.length * (command.op === 'read' ? command.repeat ?? 1 : 1);\n // A `read` of a one-element pin list with no repeat still comes back as a plain\n // value: the device only details a step that covered several readings.\n const singleton = command.op === 'read' && count === 1 && step.value !== undefined\n && step.samples === undefined;\n if (singleton) return true;\n if (step.value !== undefined) return false;\n const samples = step.samples ?? [];\n if (samples.length !== count) return false;\n return samples.every((sample, offset) => sample.io === pins[offset % pins.length]);\n });\n};\n\nconst namedSequenceResult = (\n { name, index, command }: SequenceAssociation,\n step: GpioSequenceStep,\n): GpioSequenceNamedResult => {\n const attempt = { name, index, op: command.op, elapsed: step.elapsed };\n switch (sequenceKind(command)) {\n case 'scalar':\n return {\n ...attempt,\n kind: 'scalar',\n io: step.io,\n value: step.value,\n } as GpioSequenceNamedResult;\n case 'collection':\n return {\n ...attempt,\n kind: 'collection',\n io: step.io,\n // A correlated one-reading collection carries its lone reading in `value`.\n samples: step.samples\n ?? [{ io: (step.io as number[])[0], value: step.value, elapsed: step.elapsed }],\n } as GpioSequenceNamedResult;\n default:\n return { ...attempt, kind: 'control' } as GpioSequenceNamedResult;\n }\n};\n\ntype SequenceReadRepeat<Options> = Options extends GpioSequenceReadOptions\n ? 'repeat' extends keyof Options ? Options['repeat'] : undefined\n : undefined;\ntype SequenceReadKind<Pins, Repeat> = Pins extends readonly number[] ? 'collection'\n : Repeat extends undefined | 1 ? 'scalar'\n : number extends Repeat ? 'scalar' | 'collection'\n : 'collection';\ntype SequenceWriteKind<Pins> = Pins extends readonly number[]\n ? number extends Pins['length'] ? 'scalar' | 'collection'\n : Pins['length'] extends 1 ? 'scalar' : 'collection'\n : 'scalar';\ntype SequenceWithName<Names, Name extends string, Last> = string extends Name ? Names\n : Name extends string ? Names & { [Key in Name]: Last }\n : never;\ntype SequenceNode = {\n readonly command: GpioSequenceCommand;\n readonly name?: string;\n readonly previous?: SequenceNode;\n readonly length: number;\n};\n/** A digital level, or inclusive voltage bounds for an analog pin. */\nexport type GpioSequenceExpectation = v.InferOutput<typeof sequenceExpect>;\n/** A digital level, or a voltage for an analog pin. */\nexport type GpioSequenceValue = v.InferOutput<typeof sequenceValue>;\nexport type GpioSequenceReadOptions = {\n repeat?: number;\n delay?: number;\n expect?: GpioSequenceExpectation;\n};\n/** A digital level: the strings the wire uses, or a boolean (`true` is high). */\nexport type GpioSequenceLevel = 'low' | 'high' | boolean;\nexport type GpioSequenceWaitOptions = { timeout?: number; stable_for?: number };\n/** At least one edge is required; both together are an inclusive band. */\nexport type GpioSequenceWaitVoltageOptions =\n & ({ min: number; max?: number } | { max: number; min?: number })\n & GpioSequenceWaitOptions;\n\nexport const gpioConfiguration = v.union([\n digitalOutputConfiguration,\n openDrainConfiguration,\n digitalInputConfiguration,\n analogOutputConfiguration,\n analogInputConfiguration,\n]);\nexport type GpioConfiguration = v.InferOutput<typeof gpioConfiguration>;\n\n/** @hideconstructor */\nexport class GpioApi {\n private count: number;\n\n constructor(private readonly fetch: UpFetch, info: Information) {\n this.count = info.capabilities.io.count;\n }\n\n /**\n * Resets all IO configurations to default.\n */\n reset(): Promise<void> {\n return this.fetch('/gpio/reset', { method: 'POST', parseResponse: () => {} });\n }\n\n /**\n * Access a specific digital IO pin by id.\n * @param io The IO pin id.\n * @returns The digital IO instance.\n */\n digital(io: number): DigitalIO {\n if (io < 0 || io >= this.count) {\n throw new Error(\n `Invalid GPIO pin ${io} (RESOURCE_NOT_FOUND)\\n Suggestion: Use a pin number between 0 and ${\n this.count - 1\n }\\n Path: /gpio/${io}`,\n );\n }\n\n return new DigitalIO(this.fetch, io);\n }\n\n /**\n * Access a specific analog IO pin by id.\n * @param io The IO pin id.\n * @returns The analog IO instance.\n */\n analog(io: number): AnalogIO {\n if (io < 0 || io >= this.count) {\n throw new Error(\n `Invalid GPIO pin ${io} (RESOURCE_NOT_FOUND)\\n Suggestion: Use a pin number between 0 and ${\n this.count - 1\n }\\n Path: /gpio/${io}`,\n );\n }\n\n return new AnalogIO(this.fetch, io);\n }\n\n /**\n * Holds the current state of all GPIO pins.\n * @returns The applied sync state.\n */\n hold(): Promise<SyncConfiguration> {\n return this.fetch('/gpio/sync', {\n method: 'POST',\n body: { action: 'hold' } satisfies SyncConfiguration,\n schema: syncConfiguration,\n });\n }\n\n /**\n * Releases control of the IO pins, allowing external control.\n *\n * This also sets the device as a slave.\n *\n * @returns The applied sync state.\n */\n release(): Promise<SyncConfiguration> {\n return this.fetch('/gpio/sync', {\n method: 'POST',\n body: { action: 'release' } satisfies SyncConfiguration,\n schema: syncConfiguration,\n });\n }\n\n /**\n * Reads back the current configuration of a specific IO pin.\n * @param io The IO pin id.\n * @returns The pin's current configuration.\n */\n read_config(io: number): Promise<GpioConfiguration> {\n if (io < 0 || io >= this.count) {\n throw new Error(\n `Invalid GPIO pin ${io} (RESOURCE_NOT_FOUND)\\n Suggestion: Use a pin number between 0 and ${\n this.count - 1\n }\\n Path: /gpio/${io}/config`,\n );\n }\n\n return this.fetch(`/gpio/${io}/config`, { schema: gpioConfiguration });\n }\n\n /**\n * Reads the current hold state of all GPIO pins.\n * @returns The current sync state.\n */\n read_sync(): Promise<SyncState> {\n return this.fetch('/gpio/sync', { schema: syncState });\n }\n\n /**\n * Starts a command sequence.\n *\n * The device runs every appended command back to back, holding the IO subsystem for\n * the whole run, so no other IO request interleaves. Every pin used must be\n * configured before `run()`.\n *\n * @returns An empty sequence builder.\n */\n sequence(): GpioSequence {\n return new GpioSequence(this.fetch, this.count);\n }\n}\n\n/** @hideconstructor */\nexport class DigitalIO {\n constructor(private readonly fetch: UpFetch, public readonly id: number) {}\n\n /**\n * Configure the pin as a digital input.\n * @param config The digital input configuration.\n * @returns The applied configuration.\n */\n configure_input(config: PartialDigitalInputConfiguration): Promise<DigitalInputConfiguration> {\n return this.fetch(`/gpio/${this.id}/config`, {\n method: 'PATCH',\n body: v.parse(\n digitalInputConfiguration,\n { ...config, mode: 'digital', direction: 'input' } satisfies DigitalInputConfiguration,\n ),\n schema: digitalInputConfiguration,\n });\n }\n\n /**\n * Configures the pin as a digital output.\n * @param config The digital output configuration.\n * @returns The applied configuration.\n */\n configure_output(config: PartialDigitalOutputConfiguration): Promise<DigitalOutputConfiguration> {\n config = v.parse(partialDigitalOutputConfiguration, config);\n\n const fullConfig = {\n mode: 'digital' as const,\n direction: 'output' as const,\n value: config.value,\n vol: config.vol,\n voh: config.voh,\n vil: config.vil ?? config.vol + (config.voh - config.vol) / 4,\n vih: config.vih ?? config.voh - (config.voh - config.vol) / 4,\n };\n\n return this.fetch(`/gpio/${this.id}/config`, {\n method: 'PATCH',\n body: v.parse(digitalOutputConfiguration, fullConfig),\n schema: digitalOutputConfiguration,\n });\n }\n\n /**\n * Reads the current state of the pin.\n * @returns The current state of the pin.\n */\n async read(): Promise<boolean> {\n return (await this.fetch(`/gpio/${this.id}/state`, { schema: digitalState })).value;\n }\n\n /**\n * Writes a value to the pin.\n * @param value The value to write.\n * @returns The written value.\n */\n async write(value: boolean | number): Promise<boolean> {\n return (await this.fetch(`/gpio/${this.id}/state`, {\n method: 'PUT',\n body: v.parse(digitalState, { value }),\n schema: digitalState,\n }))\n .value;\n }\n\n /**\n * Configure the pin as an open drain output.\n * @param config The open drain configuration.\n * @returns The applied configuration.\n */\n configure_open_drain(config: PartialOpenDrainConfiguration): Promise<OpenDrainConfiguration> {\n return this.fetch(`/gpio/${this.id}/config`, {\n method: 'PATCH',\n body: v.parse(\n openDrainConfiguration,\n { ...config, mode: 'digital', direction: 'open_drain' } satisfies OpenDrainConfiguration,\n ),\n schema: openDrainConfiguration,\n });\n }\n}\n\n/** @hideconstructor */\nexport class AnalogIO {\n constructor(private readonly fetch: UpFetch, public readonly id: number) {}\n\n /**\n * Configures the pin as an analog input.\n * @returns The applied configuration.\n * @returns The applied configuration.\n */\n configure_input(): Promise<AnalogInputConfiguration> {\n return this.fetch(`/gpio/${this.id}/config`, {\n method: 'PATCH',\n body: { mode: 'analog', direction: 'input' } satisfies AnalogInputConfiguration,\n schema: analogInputConfiguration,\n });\n }\n\n /**\n * Configures the pin as an analog output.\n * @param config The analog output configuration.\n * @returns The applied configuration.\n */\n configure_output(value: AnalogOutputLevel): Promise<AnalogOutputConfiguration> {\n return this.fetch(`/gpio/${this.id}/config`, {\n method: 'PATCH',\n body: v.parse(\n analogOutputConfiguration,\n { value, mode: 'analog', direction: 'output' } satisfies AnalogOutputConfiguration,\n ),\n schema: analogOutputConfiguration,\n });\n }\n\n /**\n * Reads the current state of the pin.\n * @returns The current state of the pin.\n */\n async read(): Promise<number> {\n return (await this.fetch(`/gpio/${this.id}/state`, { schema: analogState })).value;\n }\n\n /**\n * Writes a value to the pin.\n * @param value The value to write.\n * @returns The written value.\n */\n async write(value: number): Promise<number> {\n return (await this.fetch(`/gpio/${this.id}/state`, {\n method: 'PUT',\n body: { value },\n schema: analogState,\n }))\n .value;\n }\n}\n\n/**\n * A list of IO commands the device runs back to back.\n *\n * Nothing is sent until `run()`. `repeat`, `delay`, `expect` and `stable_for` are\n * device-side parameters: the builder never expands one appended command into several,\n * and never loops client-side. A builder is reusable — `run()` keeps the commands, so\n * the same sequence can be run again.\n *\n * @hideconstructor\n */\nexport class GpioSequence<Names = {}, Last = never> {\n constructor(\n private readonly fetch: UpFetch,\n private readonly count: number,\n private readonly tail?: SequenceNode,\n ) {}\n\n /**\n * Reads one pin, or several pins in the order given.\n *\n * `repeat` is the total number of readings of the whole pin list (1 when omitted) and\n * `delay` is the gap in seconds between passes: the first pass runs immediately, every\n * later pass waits `delay`, nothing waits after the last one, and nothing waits\n * between the pins of one pass. It is an end-to-start gap, not a sampling interval,\n * so the effective period is `delay` plus however long a pass takes. `expect` is\n * asserted on every reading: a boolean needs digital pins, inclusive `{ min, max }`\n * volts needs analog pins. A failed assertion fails the whole run with\n * `SEQUENCE_ASSERTION_FAILED`.\n *\n * @param io The pin, or the distinct pins to read in order.\n * @param options Repetition, inter-pass gap and assertion.\n * @returns An independent builder with this command appended.\n */\n read<\n const Pins extends number | readonly number[],\n const Options extends GpioSequenceReadOptions | undefined = undefined,\n >(\n io: Pins,\n options?: Options,\n ): GpioSequence<\n Names,\n SequenceDescriptor<'read', SequenceReadKind<Pins, SequenceReadRepeat<Options>>>\n > {\n this.pinList('read', io);\n if (options?.delay !== undefined && (options.repeat ?? 1) < 2) {\n throw new Error('read() delay needs repeat of 2 or more');\n }\n\n return this.append({\n op: 'read',\n io,\n ...(options?.repeat === undefined ? {} : { repeat: options.repeat }),\n ...(options?.delay === undefined ? {} : { delay: options.delay }),\n ...(options?.expect === undefined ? {} : { expect: options.expect }),\n });\n }\n\n /**\n * Writes one pin, or several pins in the order given.\n *\n * A single `value` is applied to every listed pin; an array pairs one value per pin,\n * in the order of `io`, and must be exactly as long as the pin list. Each pin's\n * configured mode decides what its value means, exactly like the per-pin API: on a\n * digital pin a number is a level (`0` low, anything else high), on an analog pin a\n * number is volts, and a boolean written to an analog pin is rejected by the device.\n * The pins are independent, so one command may mix a digital level and an analog\n * voltage. Closed-loop output correction still runs per pin, so a multi-pin analog\n * write costs one correction per pin. Writing a pin several times, or spacing writes\n * out, means appending more `write` commands with `delay()` between them.\n *\n * A write of one pin reports the applied `value`; a write of several reports\n * `samples`, one entry per pin in the order they were driven.\n *\n * @param io The pin, or the distinct pins to write in order.\n * @param value The value applied to every pin, or one value per pin.\n * @returns An independent builder with this command appended.\n */\n write<const Pins extends number | readonly number[]>(\n io: Pins,\n value: GpioSequenceValue | readonly GpioSequenceValue[],\n ): GpioSequence<Names, SequenceDescriptor<'write', SequenceWriteKind<Pins>>> {\n const pins = this.pinList('write', io);\n if (Array.isArray(value) && value.length !== pins.length) {\n throw new Error(`write() got ${value.length} values for ${pins.length} pins`);\n }\n\n return this.append({ op: 'write', io, value });\n }\n\n /**\n * Waits for an analog pin to read inside a voltage bound.\n *\n * The pin must be in `analog` mode; the device rejects a digital one, which\n * {@link GpioSequence.wait_level} handles instead. `min` alone waits for the pin to\n * read at or above it, `max` alone for at or below it, and the two together for the\n * inclusive band they describe; at least one is required and `min` must not be above\n * `max`. The semantics are on the sample, not the edge, so a pin already inside the\n * bound completes immediately. `stable_for` (seconds) requires the bound to hold\n * across samples spanning that long; any sample outside it restarts the window.\n * Voltages come from polled ADC samples, so an excursion shorter than the interval\n * between two samples is invisible. A wait that exceeds its `timeout` fails the whole\n * run with `SEQUENCE_TIMED_OUT`.\n *\n * @param io The pin to watch.\n * @param options The bound edges in volts, time budget and stability window.\n * @returns An independent builder with this command appended.\n */\n wait_voltage(\n io: number,\n options: GpioSequenceWaitVoltageOptions,\n ): GpioSequence<Names, SequenceDescriptor<'wait_voltage', 'scalar'>> {\n this.check(io);\n const { min, max }: { min?: number; max?: number } = options;\n if (min === undefined && max === undefined) {\n throw new Error('wait_voltage() needs min, max, or both');\n }\n if (min !== undefined && max !== undefined && min > max) {\n throw new Error(`wait_voltage() min ${min} is above max ${max}`);\n }\n\n return this.append({\n op: 'wait_voltage',\n io,\n ...(min === undefined ? {} : { min }),\n ...(max === undefined ? {} : { max }),\n ...waitFields(options),\n });\n }\n\n /**\n * Waits for a digital pin to read a level.\n *\n * The pin must be in `digital` mode; the device rejects an analog one, which\n * {@link GpioSequence.wait_voltage} handles instead. The level is resolved from the\n * pin's configured `vil`/`vih`. The semantics are on the level, not the edge, so a pin\n * that already reads the level completes immediately. `stable_for` (seconds) requires\n * the level to hold across samples spanning that long; any sample that fails the\n * condition restarts the window. Levels come from polled ADC samples, so a transition\n * shorter than the interval between two samples is invisible. A wait that exceeds its\n * `timeout` fails the whole run with `SEQUENCE_TIMED_OUT`.\n *\n * @param io The pin to watch.\n * @param level The level to wait for, as `'low'`/`'high'` or a boolean.\n * @param options Time budget and stability window.\n * @returns An independent builder with this command appended.\n */\n wait_level(\n io: number,\n level: GpioSequenceLevel,\n options?: GpioSequenceWaitOptions,\n ): GpioSequence<Names, SequenceDescriptor<'wait_level', 'scalar'>> {\n this.check(io);\n return this.append({ op: 'wait_level', io, level: wireLevel(level), ...waitFields(options) });\n }\n\n /**\n * Sleeps, holding the IO subsystem.\n * @param duration Seconds to sleep.\n * @returns An independent builder with this command appended.\n */\n delay(duration: number): GpioSequence<Names, SequenceDescriptor<'delay', 'control'>> {\n return this.append({ op: 'delay', duration });\n }\n\n /**\n * Holds synchronization, freezing the analog outputs for the rest of the sequence.\n * @returns An independent builder with this command appended.\n */\n hold(): GpioSequence<Names, SequenceDescriptor<'hold', 'control'>> {\n return this.append({ op: 'hold' });\n }\n\n /**\n * Releases synchronization, applying every output staged while it was held.\n * @returns An independent builder with this command appended.\n */\n release(): GpioSequence<Names, SequenceDescriptor<'release', 'control'>> {\n return this.append({ op: 'release' });\n }\n\n /** Names the preceding command without changing this builder or the wire request. */\n as<const Name extends string>(\n name: Name & ([Last] extends [never] ? never : Name extends keyof Names ? never : unknown),\n ): GpioSequence<SequenceWithName<Names, Name, Last>, never> {\n if (typeof name !== 'string' || name.length === 0) {\n throw new Error('Sequence name must be a nonempty string');\n }\n if (this.tail === undefined) throw new Error('No sequence command to name');\n if (this.tail.name !== undefined) throw new Error('Sequence command is already named');\n for (let node: SequenceNode | undefined = this.tail; node; node = node.previous) {\n if (node.name === name) throw new Error(`Duplicate sequence name: ${name}`);\n }\n return new GpioSequence(this.fetch, this.count, { ...this.tail, name });\n }\n\n /**\n * Runs the sequence on the device.\n *\n * A wait that times out, a sequence that exceeds its budget and a failed read\n * assertion reject with an `ApiError` whose `code` is `SEQUENCE_TIMED_OUT` or\n * `SEQUENCE_ASSERTION_FAILED`; nothing after the stopping command runs, and no\n * partial report is produced.\n *\n * @param options Total time budget in seconds, 30 when omitted.\n * @returns One result per appended command.\n */\n run(options?: { timeout?: number }): Promise<GpioSequenceReport<Names>> {\n if (this.tail === undefined) {\n throw new Error('Sequence is empty');\n }\n\n const commands: GpioSequenceCommand[] = [];\n commands.length = this.tail.length;\n const associations: SequenceAssociation[] = [];\n for (let node: SequenceNode | undefined = this.tail; node; node = node.previous) {\n const index = node.length - 1;\n commands[index] = node.command;\n if (node.name !== undefined) {\n associations.push({ name: node.name, index, command: node.command });\n }\n }\n associations.reverse();\n const timeout = options?.timeout ?? 30;\n return this\n .fetch('/gpio/sequence', {\n method: 'POST',\n body: v.parse(sequenceRequest, { timeout, commands }),\n schema: v.pipe(\n sequenceReport,\n v.check((report) => matchesSequence(report, commands), 'Invalid GPIO sequence response'),\n ),\n // The shared client aborts after one second, which every sequence longer than\n // that would hit before the device answered.\n timeout: (timeout + 2) * 1000,\n })\n .then((wire) => new GpioSequenceReport<Names>(wire, associations));\n }\n\n // The pin list of a command that accepts either form, validated the way the device\n // validates it: at least one pin, each in range, each listed at most once.\n private pinList(method: 'read' | 'write', io: number | readonly number[]): readonly number[] {\n const pins = typeof io === 'number' ? [io] : io;\n if (pins.length === 0) {\n throw new Error(`${method}() needs at least one pin`);\n }\n for (const pin of pins) {\n this.check(pin);\n if (pins.indexOf(pin) !== pins.lastIndexOf(pin)) {\n throw new Error(`${method}() lists pin ${pin} twice`);\n }\n }\n\n return pins;\n }\n\n private check(io: number): void {\n if (io < 0 || io >= this.count) {\n throw new Error(\n `Invalid GPIO pin ${io} (RESOURCE_NOT_FOUND)\\n Suggestion: Use a pin number between 0 and ${\n this.count - 1\n }\\n Path: /gpio/sequence`,\n );\n }\n }\n\n private append<Descriptor extends SequenceDescriptor>(\n command: unknown,\n ): GpioSequence<Names, Descriptor> {\n if ((this.tail?.length ?? 0) >= 65536) throw new Error('Sequence exceeds 65536 commands');\n return new GpioSequence(this.fetch, this.count, {\n command: v.parse(sequenceCommand, command),\n previous: this.tail,\n length: (this.tail?.length ?? 0) + 1,\n });\n }\n}\n\n// Only the options the caller set: an omitted option must not reach the wire, so the\n// device sees the plain shape of a bare wait.\nconst waitFields = (options?: GpioSequenceWaitOptions) => ({\n ...(options?.timeout === undefined ? {} : { timeout: options.timeout }),\n ...(options?.stable_for === undefined ? {} : { stable_for: options.stable_for }),\n});\n\n// The wire carries the level as a string; a boolean is caller sugar.\nconst wireLevel = (level: GpioSequenceLevel) =>\n typeof level === 'boolean' ? (level ? 'high' : 'low') : level;\n"],"mappings":"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"}
@@ -32,7 +32,7 @@ declare const knobEvent: Omit<v.ObjectSchema<{
32
32
  readonly button_pressed: v.BooleanSchema<undefined>;
33
33
  readonly button_held: v.BooleanSchema<undefined>;
34
34
  readonly rotation_delta: v.NumberSchema<undefined>;
35
- }, undefined>, "~types" | "~run" | "~standard" | "entries"> & {
35
+ }, undefined>, "entries" | "~run" | "~standard" | "~types"> & {
36
36
  readonly entries: Omit<{
37
37
  readonly button_pressed: v.BooleanSchema<undefined>;
38
38
  readonly button_held: v.BooleanSchema<undefined>;
@@ -148,4 +148,4 @@ declare class Knob {
148
148
  }
149
149
  //#endregion
150
150
  export { KnobEvent as a, ProgressValue as c, color as d, internalKnobEvent as f, text as h, Knob as i, Screen as l, progress as m, Color as n, PlaybackConfiguration as o, playbackConfiguration as p, HmiApi as r, Progress as s, Audio as t, ScreenText as u };
151
- //# sourceMappingURL=hmi-B-potLdl.d.cts.map
151
+ //# sourceMappingURL=hmi-BEMiVKDF.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hmi-BEMiVKDF.d.cts","names":[],"sources":["../src/api/hmi.ts"],"mappings":";;;cAGM,YAAU,EAAA,yBAAA,EAAA,yBAAA,EAAA;KACJ,aAAa,EAAE,mBAAmB;cAEjC,MAAI,EAAA;;;cAIJ,OAAK,EAAA;;;;;KAKN,QAAQ,EAAE,mBAAmB;cAEnC,eAAa,EAAA,yBAAA,EAAA,yBAAA,EAAA,sCAAA,EAAA;KACP,gBAAgB,EAAE,mBAAmB;cACpC,UAAQ,EAAA;;;KACT,WAAW,EAAE,mBAAmB;cAE/B,uBAAqB,EAAA;;;;KAOtB,wBAAwB,EAAE,mBAAmB;cAE5C,mBAAiB,EAAA;;;;;cAKxB,WAAS,KAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KACH,YAAY,EAAE,mBAAmB;;cAGhC;mBACkB;EAA7B,YAA6B,OAAO;;;;EAKpC,SAAS;;;;;EAQT,UAAU;;;;;EAQV,SAAS;;;;;EAQT,QAAQ;;;cAMG;mBACkB;EAA7B,YAA6B,OAAO;;;;;;EAO9B,MAAM,MAAM,aAAa;;;;;;EAc/B,OAAO,QAAQ,QAAQ,QAAQ;;;;;;EAazB,SAAS,MAAM,gBAAgB,QAAQ;;;;EAkB7C,SAAS;;;;EAOT,cAAc;;;cAMH;mBACkB;EAA7B,YAA6B,OAAO;;;;;;EAO9B,KAAK,QAAQ,wBAAwB,QAAQ;;;cAUxC;mBACkB;EAA7B,YAA6B,OAAO;EAEpC,kBAAU;;;;;EAEV,sBAAc;EACd,sBAAc;;;;;;EAOR,WAAW,sBAAsB,QAAQ"}
@@ -32,7 +32,7 @@ declare const knobEvent: Omit<v.ObjectSchema<{
32
32
  readonly button_pressed: v.BooleanSchema<undefined>;
33
33
  readonly button_held: v.BooleanSchema<undefined>;
34
34
  readonly rotation_delta: v.NumberSchema<undefined>;
35
- }, undefined>, "~types" | "~run" | "~standard" | "entries"> & {
35
+ }, undefined>, "entries" | "~run" | "~standard" | "~types"> & {
36
36
  readonly entries: Omit<{
37
37
  readonly button_pressed: v.BooleanSchema<undefined>;
38
38
  readonly button_held: v.BooleanSchema<undefined>;
@@ -148,4 +148,4 @@ declare class Knob {
148
148
  }
149
149
  //#endregion
150
150
  export { KnobEvent as a, ProgressValue as c, color as d, internalKnobEvent as f, text as h, Knob as i, Screen as l, progress as m, Color as n, PlaybackConfiguration as o, playbackConfiguration as p, HmiApi as r, Progress as s, Audio as t, ScreenText as u };
151
- //# sourceMappingURL=hmi-B-potLdl.d.mts.map
151
+ //# sourceMappingURL=hmi-BEMiVKDF.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hmi-BEMiVKDF.d.mts","names":[],"sources":["../src/api/hmi.ts"],"mappings":";;;cAGM,YAAU,EAAA,yBAAA,EAAA,yBAAA,EAAA;KACJ,aAAa,EAAE,mBAAmB;cAEjC,MAAI,EAAA;;;cAIJ,OAAK,EAAA;;;;;KAKN,QAAQ,EAAE,mBAAmB;cAEnC,eAAa,EAAA,yBAAA,EAAA,yBAAA,EAAA,sCAAA,EAAA;KACP,gBAAgB,EAAE,mBAAmB;cACpC,UAAQ,EAAA;;;KACT,WAAW,EAAE,mBAAmB;cAE/B,uBAAqB,EAAA;;;;KAOtB,wBAAwB,EAAE,mBAAmB;cAE5C,mBAAiB,EAAA;;;;;cAKxB,WAAS,KAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KACH,YAAY,EAAE,mBAAmB;;cAGhC;mBACkB;EAA7B,YAA6B,OAAO;;;;EAKpC,SAAS;;;;;EAQT,UAAU;;;;;EAQV,SAAS;;;;;EAQT,QAAQ;;;cAMG;mBACkB;EAA7B,YAA6B,OAAO;;;;;;EAO9B,MAAM,MAAM,aAAa;;;;;;EAc/B,OAAO,QAAQ,QAAQ,QAAQ;;;;;;EAazB,SAAS,MAAM,gBAAgB,QAAQ;;;;EAkB7C,SAAS;;;;EAOT,cAAc;;;cAMH;mBACkB;EAA7B,YAA6B,OAAO;;;;;;EAO9B,KAAK,QAAQ,wBAAwB,QAAQ;;;cAUxC;mBACkB;EAA7B,YAA6B,OAAO;EAEpC,kBAAU;;;;;EAEV,sBAAc;EACd,sBAAc;;;;;;EAOR,WAAW,sBAAsB,QAAQ"}
package/build/hmi.cjs CHANGED
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./rolldown-runtime-CMqjfN_6.cjs");let t=require("valibot");t=e.t(t,1);const n=t.pipe(t.string(),t.maxLength(1024)),r=t.object({text:n}),i=t.optional(t.pipe(t.string(),t.length(7),t.hexColor())),a=t.object({text:i,progress:i,background:i}),o=t.pipe(t.number(),t.minValue(0),t.maxValue(100)),s=t.object({progress:o}),c=t.object({sound_id:t.picklist([`success`,`warning`,`failure`,`notification_1`,`notification_2`,`imperial_march`]),volume:t.pipe(t.number(),t.minValue(0),t.maxValue(100))}),l=t.object({button_pressed:t.boolean(),button_held:t.boolean(),rotation_delta:t.number()});t.omit(l,[`button_held`]);var u=class{fetch;constructor(e){this.fetch=e}reset(){return this.fetch(`/hmi/reset`,{method:`POST`,parseResponse:()=>{}})}screen(){return new d(this.fetch)}audio(){return new f(this.fetch)}knob(){return new p(this.fetch)}},d=class{fetch;constructor(e){this.fetch=e}async print(e){return(await this.fetch(`/hmi/screen/text`,{method:`POST`,body:t.parse(r,{text:e}),schema:r})).text}colors(e){return this.fetch(`/hmi/screen/colors`,{method:`PATCH`,body:t.parse(a,e),schema:a})}async progress(e){return e==0?await this.fetch(`/hmi/screen/progress`,{method:`DELETE`,parseResponse:()=>({progress:0})}):this.fetch(`/hmi/screen/progress`,{method:`PUT`,body:t.parse(s,{progress:e}),schema:s})}clear(){return this.fetch(`/hmi/screen/clear`,{method:`POST`,parseResponse:()=>{}})}clear_text(){return this.fetch(`/hmi/screen/text`,{method:`DELETE`,parseResponse:()=>{}})}},f=class{fetch;constructor(e){this.fetch=e}async play(e){return this.fetch(`/hmi/speaker/play`,{method:`POST`,body:t.parse(c,e),schema:c})}},p=class{fetch;constructor(e){this.fetch=e}read_event=()=>this.fetch(`/hmi/knob/get_knob_event`,{schema:l});is_button_held=async()=>(await this.read_event()).button_held;is_knob_turned=async()=>Math.abs((await this.read_event()).rotation_delta)>=4;async wait_event(e){await this.read_event();let t=0,n=Math.min(50,(e??500)/10),r=Date.now();for(;e===void 0||Date.now()-r<e;){let e=await this.read_event();if(t+=e.rotation_delta,e.button_pressed||Math.abs(t)>=4)return{button_pressed:e.button_pressed,rotation_delta:Math.sign(t)};await new Promise(e=>setTimeout(e,n))}return null}};exports.Audio=f,exports.HmiApi=u,exports.Knob=p,exports.Screen=d,exports.color=a,exports.internalKnobEvent=l,exports.playbackConfiguration=c,exports.progress=s,exports.text=r;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./rolldown-runtime-BocRIvOZ.cjs");let t=require("valibot");t=e.t(t,1);const n=t.pipe(t.string(),t.maxLength(1024)),r=t.object({text:n}),i=t.optional(t.pipe(t.string(),t.length(7),t.hexColor())),a=t.object({text:i,progress:i,background:i}),o=t.pipe(t.number(),t.minValue(0),t.maxValue(100)),s=t.object({progress:o}),c=t.object({sound_id:t.picklist([`success`,`warning`,`failure`,`notification_1`,`notification_2`,`imperial_march`]),volume:t.pipe(t.number(),t.minValue(0),t.maxValue(100))}),l=t.object({button_pressed:t.boolean(),button_held:t.boolean(),rotation_delta:t.number()});t.omit(l,[`button_held`]);var u=class{fetch;constructor(e){this.fetch=e}reset(){return this.fetch(`/hmi/reset`,{method:`POST`,parseResponse:()=>{}})}screen(){return new d(this.fetch)}audio(){return new f(this.fetch)}knob(){return new p(this.fetch)}},d=class{fetch;constructor(e){this.fetch=e}async print(e){return(await this.fetch(`/hmi/screen/text`,{method:`POST`,body:t.parse(r,{text:e}),schema:r})).text}colors(e){return this.fetch(`/hmi/screen/colors`,{method:`PATCH`,body:t.parse(a,e),schema:a})}async progress(e){return e==0?await this.fetch(`/hmi/screen/progress`,{method:`DELETE`,parseResponse:()=>({progress:0})}):this.fetch(`/hmi/screen/progress`,{method:`PUT`,body:t.parse(s,{progress:e}),schema:s})}clear(){return this.fetch(`/hmi/screen/clear`,{method:`POST`,parseResponse:()=>{}})}clear_text(){return this.fetch(`/hmi/screen/text`,{method:`DELETE`,parseResponse:()=>{}})}},f=class{fetch;constructor(e){this.fetch=e}async play(e){return this.fetch(`/hmi/speaker/play`,{method:`POST`,body:t.parse(c,e),schema:c})}},p=class{fetch;constructor(e){this.fetch=e}read_event=()=>this.fetch(`/hmi/knob/get_knob_event`,{schema:l});is_button_held=async()=>(await this.read_event()).button_held;is_knob_turned=async()=>Math.abs((await this.read_event()).rotation_delta)>=4;async wait_event(e){await this.read_event();let t=0,n=Math.min(50,(e??500)/10),r=Date.now();for(;e===void 0||Date.now()-r<e;){let e=await this.read_event();if(t+=e.rotation_delta,e.button_pressed||Math.abs(t)>=4)return{button_pressed:e.button_pressed,rotation_delta:Math.sign(t)};await new Promise(e=>setTimeout(e,n))}return null}};exports.Audio=f,exports.HmiApi=u,exports.Knob=p,exports.Screen=d,exports.color=a,exports.internalKnobEvent=l,exports.playbackConfiguration=c,exports.progress=s,exports.text=r;
2
2
  //# sourceMappingURL=hmi.cjs.map
package/build/hmi.d.cts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as KnobEvent, c as ProgressValue, d as color, f as internalKnobEvent, h as text, i as Knob, l as Screen, m as progress, n as Color, o as PlaybackConfiguration, p as playbackConfiguration, r as HmiApi, s as Progress, t as Audio, u as ScreenText } from "./hmi-B-potLdl.cjs";
1
+ import { a as KnobEvent, c as ProgressValue, d as color, f as internalKnobEvent, h as text, i as Knob, l as Screen, m as progress, n as Color, o as PlaybackConfiguration, p as playbackConfiguration, r as HmiApi, s as Progress, t as Audio, u as ScreenText } from "./hmi-BEMiVKDF.cjs";
2
2
  export { Audio, Color, HmiApi, Knob, KnobEvent, PlaybackConfiguration, Progress, ProgressValue, Screen, ScreenText, color, internalKnobEvent, playbackConfiguration, progress, text };
package/build/hmi.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as KnobEvent, c as ProgressValue, d as color, f as internalKnobEvent, h as text, i as Knob, l as Screen, m as progress, n as Color, o as PlaybackConfiguration, p as playbackConfiguration, r as HmiApi, s as Progress, t as Audio, u as ScreenText } from "./hmi-B-potLdl.mjs";
1
+ import { a as KnobEvent, c as ProgressValue, d as color, f as internalKnobEvent, h as text, i as Knob, l as Screen, m as progress, n as Color, o as PlaybackConfiguration, p as playbackConfiguration, r as HmiApi, s as Progress, t as Audio, u as ScreenText } from "./hmi-BEMiVKDF.mjs";
2
2
  export { Audio, Color, HmiApi, Knob, KnobEvent, PlaybackConfiguration, Progress, ProgressValue, Screen, ScreenText, color, internalKnobEvent, playbackConfiguration, progress, text };
@@ -1,9 +1,9 @@
1
- import { s as ComApi } from "./com-DN1l6xqC.mjs";
2
- import { i as EventsApi } from "./events-Cf7iAMZP.mjs";
1
+ import { s as ComApi } from "./com-Bkkgrsep.mjs";
2
+ import { i as EventsApi } from "./events-8aTmwMUi.mjs";
3
3
  import { Information, ManagementApi } from "./management.mjs";
4
- import { s as GpioApi } from "./gpio-Dk-s_yMc.mjs";
5
- import { r as HmiApi } from "./hmi-B-potLdl.mjs";
6
- import { i as PowerApi } from "./power-BZmXOJyK.mjs";
4
+ import { s as GpioApi } from "./gpio-5-tRkdTW.mjs";
5
+ import { r as HmiApi } from "./hmi-BEMiVKDF.mjs";
6
+ import { i as PowerApi } from "./power-D08VFff6.mjs";
7
7
  import { n as RelaysApi } from "./relays-TADiLsPk.mjs";
8
8
  import { t as SessionApi } from "./session-qWW9mqWH.mjs";
9
9
  //#region src/at1000.d.ts
@@ -21,15 +21,6 @@ declare class ApiError extends Error {
21
21
  path: string;
22
22
  });
23
23
  }
24
- /**
25
- * Formats a host into a URL authority. Returns `host` unchanged when it already
26
- * carries an explicit port; otherwise appends `fallbackPort` (the device's
27
- * mDNS-advertised port when known, else the default 8080). Bare IPv6 literals
28
- * are bracketed. Idempotent: re-formatting an authority is a no-op.
29
- */
30
- declare function format_host_for_url(host: string, fallbackPort?: number): string;
31
- /** Returns the bare host (IP or hostname) from a URL authority, dropping any port. */
32
- declare function host_without_port(host: string): string;
33
24
  /** Options for opening a device. */
34
25
  interface OpenOptions {
35
26
  /** Open read-only: skip `session/open`, mint no token, send no session header. */
@@ -99,5 +90,16 @@ declare class AT1000Base {
99
90
  }): Promise<AT1000Base>;
100
91
  }
101
92
  //#endregion
102
- export { host_without_port as a, format_host_for_url as i, ApiError as n, OpenOptions as r, AT1000Base as t };
103
- //# sourceMappingURL=at1000-gm586Tc9.d.mts.map
93
+ //#region src/host.d.ts
94
+ /**
95
+ * Formats a host into a URL authority. Returns `host` unchanged when it already
96
+ * carries an explicit port; otherwise appends `fallbackPort` (the device's
97
+ * mDNS-advertised port when known, else the default 8080). Bare IPv6 literals
98
+ * are bracketed. Idempotent: re-formatting an authority is a no-op.
99
+ */
100
+ declare function format_host_for_url(host: string, fallbackPort?: number): string;
101
+ /** Returns the bare host (IP or hostname) from a URL authority, dropping any port. */
102
+ declare function host_without_port(host: string): string;
103
+ //#endregion
104
+ export { OpenOptions as a, ApiError as i, host_without_port as n, AT1000Base as r, format_host_for_url as t };
105
+ //# sourceMappingURL=host-BBjSKRqs.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-BBjSKRqs.d.mts","names":[],"sources":["../src/at1000.ts","../src/host.ts"],"mappings":";;;;;;;;;;cAaa,iBAAiB;WACnB;;WAEA;WACA;WACA;EAET,YAAY;IAAQ;IAAc;IAAiB;IAAoB;;;;UAoDxD;;EAEf;;EAEA;;;cAIW;;;;WAIK;;;;WAIA,MAAM;;;;;WAKN;;;;;WAKA;UAER;;;;WAIQ,KAAK;;;;WAIL,KAAK;;;;WAIL,MAAM;;;;WAIN,YAAY;;;;WAIZ,OAAO;;;;WAIP,QAAQ;;;;WAIR,QAAQ;;;;WAIR,SAAS;EAEzB,YAAY,cAAc,MAAM,aAAa,gBAAgB;EA4BvD,SAAK;mBAQY,SACrB,cACA,UAAU,aACV;IAAY;IAA4B;IAAkB;MACzD,QAAQ;;;;;;;;;;iBCtKG,oBAAoB,cAAc;;iBAgBlC,kBAAkB"}
@@ -1,9 +1,9 @@
1
- import { s as ComApi } from "./com-DN1l6xqC.cjs";
2
- import { i as EventsApi } from "./events-Cf7iAMZP.cjs";
1
+ import { s as ComApi } from "./com-Bkkgrsep.cjs";
2
+ import { i as EventsApi } from "./events-8aTmwMUi.cjs";
3
3
  import { Information, ManagementApi } from "./management.cjs";
4
- import { s as GpioApi } from "./gpio-CsxbjhA_.cjs";
5
- import { r as HmiApi } from "./hmi-B-potLdl.cjs";
6
- import { i as PowerApi } from "./power-B8QFbKdP.cjs";
4
+ import { s as GpioApi } from "./gpio-D3QEeLKh.cjs";
5
+ import { r as HmiApi } from "./hmi-BEMiVKDF.cjs";
6
+ import { i as PowerApi } from "./power-B3oUS0wU.cjs";
7
7
  import { n as RelaysApi } from "./relays-TADiLsPk.cjs";
8
8
  import { t as SessionApi } from "./session-qWW9mqWH.cjs";
9
9
  //#region src/at1000.d.ts
@@ -21,15 +21,6 @@ declare class ApiError extends Error {
21
21
  path: string;
22
22
  });
23
23
  }
24
- /**
25
- * Formats a host into a URL authority. Returns `host` unchanged when it already
26
- * carries an explicit port; otherwise appends `fallbackPort` (the device's
27
- * mDNS-advertised port when known, else the default 8080). Bare IPv6 literals
28
- * are bracketed. Idempotent: re-formatting an authority is a no-op.
29
- */
30
- declare function format_host_for_url(host: string, fallbackPort?: number): string;
31
- /** Returns the bare host (IP or hostname) from a URL authority, dropping any port. */
32
- declare function host_without_port(host: string): string;
33
24
  /** Options for opening a device. */
34
25
  interface OpenOptions {
35
26
  /** Open read-only: skip `session/open`, mint no token, send no session header. */
@@ -99,5 +90,16 @@ declare class AT1000Base {
99
90
  }): Promise<AT1000Base>;
100
91
  }
101
92
  //#endregion
102
- export { host_without_port as a, format_host_for_url as i, ApiError as n, OpenOptions as r, AT1000Base as t };
103
- //# sourceMappingURL=at1000-tUTVczQa.d.cts.map
93
+ //#region src/host.d.ts
94
+ /**
95
+ * Formats a host into a URL authority. Returns `host` unchanged when it already
96
+ * carries an explicit port; otherwise appends `fallbackPort` (the device's
97
+ * mDNS-advertised port when known, else the default 8080). Bare IPv6 literals
98
+ * are bracketed. Idempotent: re-formatting an authority is a no-op.
99
+ */
100
+ declare function format_host_for_url(host: string, fallbackPort?: number): string;
101
+ /** Returns the bare host (IP or hostname) from a URL authority, dropping any port. */
102
+ declare function host_without_port(host: string): string;
103
+ //#endregion
104
+ export { OpenOptions as a, ApiError as i, host_without_port as n, AT1000Base as r, format_host_for_url as t };
105
+ //# sourceMappingURL=host-DlP73amZ.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-DlP73amZ.d.cts","names":[],"sources":["../src/at1000.ts","../src/host.ts"],"mappings":";;;;;;;;;;cAaa,iBAAiB;WACnB;;WAEA;WACA;WACA;EAET,YAAY;IAAQ;IAAc;IAAiB;IAAoB;;;;UAoDxD;;EAEf;;EAEA;;;cAIW;;;;WAIK;;;;WAIA,MAAM;;;;;WAKN;;;;;WAKA;UAER;;;;WAIQ,KAAK;;;;WAIL,KAAK;;;;WAIL,MAAM;;;;WAIN,YAAY;;;;WAIZ,OAAO;;;;WAIP,QAAQ;;;;WAIR,QAAQ;;;;WAIR,SAAS;EAEzB,YAAY,cAAc,MAAM,aAAa,gBAAgB;EA4BvD,SAAK;mBAQY,SACrB,cACA,UAAU,aACV;IAAY;IAA4B;IAAkB;MACzD,QAAQ;;;;;;;;;;iBCtKG,oBAAoB,cAAc;;iBAgBlC,kBAAkB"}