UNPKG

ocearo-ui

Version:

Ocean Robot UI: 3D visualization dashboard for signalk

1 lines 17.2 kB
(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,91440,e=>{"use strict";var t=e.i(43476),a=e.i(71645),s=e.i(46932),o=e.i(88653),n=e.i(67561),i=e.i(46991),l=e.i(85709),d=e.i(66799),r=e.i(83402),c=e.i(48390),u=e.i(49721),x=e.i(68757);e.i(85269);var h=e.i(22831);function g(){let{t:e}=(0,h.useTranslation)(),g=r.default.get("debugMode"),m=(0,a.useMemo)(()=>["navigation.headingTrue","navigation.headingMagnetic","environment.wind.angleApparent","steering.rudderAngle","steering.autopilot.state","steering.autopilot.mode","steering.autopilot.target.headingTrue","steering.autopilot.target.windAngleApparent"],[]),b=(0,l.useSignalKPaths)(m),f=b["navigation.headingTrue"]||b["navigation.headingMagnetic"];b["environment.wind.angleApparent"],b["steering.rudderAngle"];let[v,j]=(0,a.useState)("control"),{nightMode:y}=(0,n.useOcearoContext)(),N="text-hud-main",w=y?"text-oNight":"text-hud-secondary",C=y?"text-oNight/70":"text-hud-muted",[k,T]=(0,a.useState)(null),[A,S]=(0,a.useState)([]),[$,R]=(0,a.useState)("default"),[P,G]=(0,a.useState)(!0),[L,I]=(0,a.useState)(null),[M,D]=(0,a.useState)(!1),[F,B]=(0,a.useState)(null),[O,U]=(0,a.useState)(!1),E=a.default.useRef(b);E.current=b;let H=(0,a.useCallback)(async()=>{try{I(null);let e=await d.default.isAutopilotAvailable();if(D(e),!e){let e=E.current,t=e["steering.autopilot.state"],a=e["steering.autopilot.mode"],s=e["steering.autopilot.target.headingTrue"]||e["steering.autopilot.target.windAngleApparent"];T({state:t||(g?"standby":"off-line"),mode:a||(g?"compass":null),target:s||(g?1.57:null),engaged:"enabled"===t});return}let t=await d.default.getAutopilotDevices();S(t),t.length>0&&!t.includes($)&&R(t[0]);let a=await d.default.getAutopilotData($);T(a)}catch(e){console.error("AutopilotView: Failed to fetch autopilot data:",e),I(e.message)}finally{G(!1)}},[$,g]),Z=(0,a.useCallback)(async()=>{try{let e=await (0,c.makeOcearoCoreApiCall)("/api/controller/config");B(e),U(e?.connected||!1)}catch(e){console.warn("AutopilotView: Could not fetch controller config:",e.message),B(null)}},[]);(0,a.useEffect)(()=>{H(),Z();let e=setInterval(()=>{H()},2e3);return()=>clearInterval(e)},[H,Z]);let K=async()=>{try{I(null),await d.default.engageAutopilot($),await H()}catch(t){I(e("autopilot.failedToEngage",{message:t.message}))}},Y=async()=>{try{I(null),await d.default.disengageAutopilot($),await H()}catch(t){I(e("autopilot.failedToDisengage",{message:t.message}))}},z=async t=>{try{I(null),await d.default.setAutopilotMode(t,$),await H()}catch(t){I(e("autopilot.failedToSetMode",{message:t.message}))}},V=async t=>{try{I(null);let e=t*Math.PI/180;await d.default.adjustAutopilotTarget(e,$),await H()}catch(t){I(e("autopilot.failedToAdjustHeading",{message:t.message}))}},X=async t=>{try{I(null);let e=t*Math.PI/180;await d.default.setAutopilotTarget(e,$),await H()}catch(t){I(e("autopilot.failedToSetHeading",{message:t.message}))}},q=async t=>{try{I(null),await d.default.autopilotTack(t,$),await H()}catch(t){I(e("autopilot.failedToTack",{message:t.message}))}},J=async t=>{try{I(null),await d.default.autopilotGybe(t,$),await H()}catch(t){I(e("autopilot.failedToGybe",{message:t.message}))}},W=async t=>{try{await (0,c.makeOcearoCoreApiCall)("/api/controller/config",{method:"PUT",body:JSON.stringify(t)}),B(t)}catch(t){I(e("autopilot.failedToSaveConfig",{message:t.message}))}},Q=e=>{switch(e){case"compass":default:return x.faCompass;case"wind":return x.faWind;case"gps":return x.faSatellite;case"route":return x.faRoute;case"dodge":return x.faAnchor}},_=e=>{if(null==e)return"---°";let t=(0,i.toDegrees)(e);return`${t}\xb0`};return(0,t.jsxs)("div",{className:"flex flex-col h-full bg-rightPaneBg overflow-hidden",children:[(0,t.jsx)("div",{className:"flex border-b border-hud bg-hud-bg",children:[{id:"control",label:e("autopilot.control"),icon:x.faCompass},{id:"controller",label:e("autopilot.controller"),icon:x.faGamepad}].map(e=>(0,t.jsxs)("button",{onClick:()=>j(e.id),className:`flex-1 py-3 px-2 text-xs font-black uppercase flex items-center justify-center transition-all duration-500 ${v===e.id?"text-oGreen border-b-2 border-oGreen bg-hud-bg":"text-hud-secondary hover:text-hud-main tesla-hover"}`,children:[(0,t.jsx)(u.FontAwesomeIcon,{icon:e.icon,className:"mr-2"}),e.label]},e.id))}),(0,t.jsx)(o.AnimatePresence,{children:L&&(0,t.jsxs)(s.motion.div,{initial:{opacity:0,height:0},animate:{opacity:1,height:"auto"},exit:{opacity:0,height:0},className:"bg-oRed/20 text-oRed p-3 rounded-lg mx-4 mt-4 border border-oRed/30",children:[(0,t.jsx)(u.FontAwesomeIcon,{icon:x.faExclamationTriangle,className:"mr-2"}),L]})}),A.length>1&&(0,t.jsx)("div",{className:"px-4 pt-4",children:(0,t.jsx)("select",{value:$,onChange:e=>R(e.target.value),className:"bg-hud-elevated text-hud-main rounded px-3 py-2 w-full border border-hud focus:border-oGreen/50 focus:outline-none transition-all",children:A.map(e=>(0,t.jsx)("option",{value:e,children:e},e))})}),(0,t.jsx)("div",{className:"flex-1 min-h-0 overflow-auto scrollbar-hide",children:(0,t.jsx)(o.AnimatePresence,{mode:"wait",children:P?(0,t.jsx)(s.motion.div,{initial:{opacity:0},animate:{opacity:1},exit:{opacity:0},className:"flex items-center justify-center h-32",children:(0,t.jsx)("div",{className:"text-hud-main",children:"Loading..."})},"loading"):(0,t.jsx)(s.motion.div,{initial:{opacity:0,x:10},animate:{opacity:1,x:0},exit:{opacity:0,x:-10},transition:{duration:.4,ease:"easeOut"},className:"p-3",children:"control"===v?(0,t.jsxs)("div",{className:"space-y-3",children:[(0,t.jsxs)("div",{className:"tesla-card p-3 border border-hud bg-hud-bg",children:[(0,t.jsxs)("div",{className:"grid grid-cols-3 gap-2 text-center",children:[(0,t.jsxs)("div",{children:[(0,t.jsx)("div",{className:`text-2xl mb-1 ${(e=>{switch(e){case"enabled":return"text-oGreen";case"standby":return"text-oYellow";case"disabled":default:return"text-hud-muted";case"off-line":return"text-oRed"}})(k?.state)}`,children:(0,t.jsx)(u.FontAwesomeIcon,{icon:(e=>{switch(e){case"enabled":return x.faCheckCircle;case"standby":return x.faPause;case"disabled":return x.faBan;case"off-line":return x.faTimesCircle;default:return x.faExclamationTriangle}})(k?.state)})}),(0,t.jsx)("div",{className:`text-xs ${w} font-bold`,children:e("autopilot.state")}),(0,t.jsx)("div",{className:`text-sm ${N} font-black capitalize`,children:k?.state||e("autopilot.unknown")})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)("div",{className:"text-2xl mb-1 text-oBlue",children:(0,t.jsx)(u.FontAwesomeIcon,{icon:Q(k?.mode)})}),(0,t.jsx)("div",{className:`text-xs ${w} font-bold`,children:e("autopilot.mode")}),(0,t.jsx)("div",{className:`text-sm ${N} font-black capitalize`,children:k?.mode||e("autopilot.none")})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)("div",{className:"text-2xl mb-1 text-oYellow",children:(0,t.jsx)(u.FontAwesomeIcon,{icon:x.faLocationArrow})}),(0,t.jsx)("div",{className:`text-xs ${w} font-bold`,children:e("autopilot.target")}),(0,t.jsx)("div",{className:`text-sm ${N} font-black`,children:_(k?.target)})]})]}),(0,t.jsxs)("div",{className:"mt-3 pt-3 border-t border-hud text-center",children:[(0,t.jsx)("div",{className:`text-xs ${w} font-bold uppercase`,children:e("autopilot.currentHeading")}),(0,t.jsx)("div",{className:`text-4xl font-black ${N}`,children:_(f)})]})]}),(0,t.jsxs)("div",{className:"grid grid-cols-2 gap-3",children:[(0,t.jsxs)("button",{onClick:K,disabled:k?.state==="enabled"||k?.state==="off-line",className:`py-3 rounded font-black text-base uppercase transition-all ${k?.state==="enabled"?"bg-hud-bg text-hud-dim cursor-not-allowed border border-hud":"bg-oGreen hover:bg-green-600 text-hud-main shadow-lg shadow-oGreen/20"}`,children:[(0,t.jsx)(u.FontAwesomeIcon,{icon:x.faPlay,className:"mr-2"}),e("autopilot.engage")]}),(0,t.jsxs)("button",{onClick:Y,disabled:k?.state!=="enabled",className:`py-3 rounded font-black text-base uppercase transition-all ${k?.state!=="enabled"?"bg-hud-bg text-hud-dim cursor-not-allowed border border-hud":"bg-oRed hover:bg-red-600 text-hud-main shadow-lg shadow-oRed/20"}`,children:[(0,t.jsx)(u.FontAwesomeIcon,{icon:x.faStop,className:"mr-2"}),e("autopilot.disengage")]})]}),(0,t.jsxs)("div",{className:"tesla-card p-3 border border-hud bg-hud-bg",children:[(0,t.jsx)("div",{className:`text-xs font-black uppercase ${w} mb-3`,children:e("autopilot.modeSelection")}),(0,t.jsx)("div",{className:"grid grid-cols-4 gap-2",children:["compass","wind","gps","route"].map(e=>(0,t.jsxs)("button",{onClick:()=>z(e),className:`py-2 rounded font-bold transition-all flex flex-col items-center border ${k?.mode===e?"bg-oBlue text-hud-main border-oBlue shadow-lg shadow-oBlue/20":"bg-hud-bg text-hud-secondary border-hud hover:bg-hud-elevated"}`,children:[(0,t.jsx)(u.FontAwesomeIcon,{icon:Q(e),className:"text-lg mb-1"}),(0,t.jsx)("span",{className:"text-xs uppercase",children:e})]},e))})]}),(0,t.jsxs)("div",{className:"tesla-card p-3 border border-hud bg-hud-bg",children:[(0,t.jsx)("div",{className:`text-xs font-black uppercase ${w} mb-3`,children:e("autopilot.targetAdjustment")}),(0,t.jsxs)("div",{className:"grid grid-cols-4 gap-2",children:[(0,t.jsx)("button",{onClick:()=>V(-10),className:"py-3 bg-oRed/40 hover:bg-oRed/60 text-hud-main rounded border border-oRed/50 font-black text-sm",children:"-10°"}),(0,t.jsx)("button",{onClick:()=>V(-1),className:"py-3 bg-oRed/20 hover:bg-oRed/40 text-hud-main rounded border border-oRed/30 font-black text-sm",children:"-1°"}),(0,t.jsx)("button",{onClick:()=>V(1),className:"py-3 bg-oGreen/20 hover:bg-oGreen/40 text-hud-main rounded border border-oGreen/30 font-black text-sm",children:"+1°"}),(0,t.jsx)("button",{onClick:()=>V(10),className:"py-3 bg-oGreen/40 hover:bg-oGreen/60 text-hud-main rounded border border-oGreen/50 font-black text-sm",children:"+10°"})]}),(0,t.jsxs)("button",{onClick:()=>f&&X((0,i.toDegrees)(f)),disabled:!f,className:"w-full mt-3 py-2.5 bg-hud-bg hover:bg-hud-elevated text-hud-main rounded border border-hud font-bold text-xs uppercase",children:[(0,t.jsx)(u.FontAwesomeIcon,{icon:x.faCompass,className:"mr-2"}),e("autopilot.syncTargetToHeading")]})]}),(0,t.jsxs)("div",{className:"tesla-card p-3 border border-hud bg-hud-bg",children:[(0,t.jsx)("div",{className:`text-xs font-black uppercase ${w} mb-3`,children:e("autopilot.maneuvers")}),(0,t.jsxs)("div",{className:"grid grid-cols-2 gap-4",children:[(0,t.jsxs)("div",{children:[(0,t.jsx)("div",{className:`text-xs font-black uppercase ${C} mb-2 text-center`,children:e("autopilot.tack")}),(0,t.jsxs)("div",{className:"grid grid-cols-2 gap-2",children:[(0,t.jsx)("button",{onClick:()=>q("port"),className:"py-2 bg-hud-bg hover:bg-hud-elevated text-hud-main rounded border border-hud font-bold text-xs",children:e("autopilot.port")}),(0,t.jsx)("button",{onClick:()=>q("starboard"),className:"py-2 bg-hud-bg hover:bg-hud-elevated text-hud-main rounded border border-hud font-bold text-xs",children:e("autopilot.stbd")})]})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)("div",{className:`text-xs font-black uppercase ${C} mb-2 text-center`,children:e("autopilot.gybe")}),(0,t.jsxs)("div",{className:"grid grid-cols-2 gap-2",children:[(0,t.jsx)("button",{onClick:()=>J("port"),className:"py-2 bg-hud-bg hover:bg-hud-elevated text-hud-main rounded border border-hud font-bold text-xs",children:e("autopilot.port")}),(0,t.jsx)("button",{onClick:()=>J("starboard"),className:"py-2 bg-hud-bg hover:bg-hud-elevated text-hud-main rounded border border-hud font-bold text-xs",children:e("autopilot.stbd")})]})]})]})]})]}):(0,t.jsxs)("div",{className:"space-y-3",children:[(0,t.jsxs)("div",{className:"tesla-card p-3 border border-hud bg-hud-bg",children:[(0,t.jsxs)("div",{className:"flex items-center justify-between mb-3",children:[(0,t.jsxs)("div",{className:"flex items-center space-x-3",children:[(0,t.jsx)(u.FontAwesomeIcon,{icon:x.faGamepad,className:`text-xl ${O?"text-oGreen":"text-hud-muted"}`}),(0,t.jsxs)("div",{children:[(0,t.jsx)("div",{className:`text-sm font-bold ${N}`,children:e("autopilot.controller")}),(0,t.jsx)("div",{className:`text-xs ${O?"text-oGreen":"text-hud-muted"} font-bold`,children:O?e("autopilot.connected"):e("autopilot.notConnected")})]})]}),(0,t.jsx)("button",{onClick:Z,className:"p-2 text-hud-secondary hover:text-hud-main",children:(0,t.jsx)(u.FontAwesomeIcon,{icon:x.faSync,className:"text-sm"})})]}),!O&&(0,t.jsxs)("div",{className:`text-xs ${C} bg-hud-elevated border border-hud rounded p-2.5 font-bold`,children:[(0,t.jsx)(u.FontAwesomeIcon,{icon:x.faExclamationTriangle,className:"text-oYellow mr-2"}),e("autopilot.connectController")]})]}),(0,t.jsxs)("div",{className:"tesla-card p-3 border border-hud bg-hud-bg",children:[(0,t.jsx)("div",{className:`text-xs font-black uppercase ${w} mb-3`,children:e("autopilot.buttonMappings")}),(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsx)(p,{label:e("autopilot.engageAutopilot"),button:F?.mappings?.engage||"X",onChange:e=>W({...F,mappings:{...F?.mappings,engage:e}}),primaryTextClass:N,secondaryTextClass:w}),(0,t.jsx)(p,{label:e("autopilot.disengageAutopilot"),button:F?.mappings?.disengage||"Circle",onChange:e=>W({...F,mappings:{...F?.mappings,disengage:e}}),primaryTextClass:N,secondaryTextClass:w}),(0,t.jsx)("div",{className:"border-t border-hud pt-2 mt-2",children:(0,t.jsx)("div",{className:`text-xs font-black uppercase ${C} mb-2`,children:e("autopilot.headingControl")})}),(0,t.jsx)(p,{label:e("autopilot.headingMinus1"),button:F?.mappings?.headingMinus1||"D-Pad Left",onChange:e=>W({...F,mappings:{...F?.mappings,headingMinus1:e}}),primaryTextClass:N,secondaryTextClass:w}),(0,t.jsx)(p,{label:e("autopilot.headingPlus1"),button:F?.mappings?.headingPlus1||"D-Pad Right",onChange:e=>W({...F,mappings:{...F?.mappings,headingPlus1:e}}),primaryTextClass:N,secondaryTextClass:w}),(0,t.jsx)(p,{label:e("autopilot.headingMinus10"),button:F?.mappings?.headingMinus10||"L1",onChange:e=>W({...F,mappings:{...F?.mappings,headingMinus10:e}}),primaryTextClass:N,secondaryTextClass:w}),(0,t.jsx)(p,{label:e("autopilot.headingPlus10"),button:F?.mappings?.headingPlus10||"R1",onChange:e=>W({...F,mappings:{...F?.mappings,headingPlus10:e}}),primaryTextClass:N,secondaryTextClass:w}),(0,t.jsx)("div",{className:"border-t border-hud pt-2 mt-2",children:(0,t.jsx)("div",{className:`text-xs font-black uppercase ${C} mb-2`,children:e("autopilot.rudderControl")})}),(0,t.jsx)(p,{label:e("autopilot.rudderLeft"),button:F?.mappings?.rudderLeft||"Left Stick Left",onChange:e=>W({...F,mappings:{...F?.mappings,rudderLeft:e}}),primaryTextClass:N,secondaryTextClass:w}),(0,t.jsx)(p,{label:e("autopilot.rudderRight"),button:F?.mappings?.rudderRight||"Left Stick Right",onChange:e=>W({...F,mappings:{...F?.mappings,rudderRight:e}}),primaryTextClass:N,secondaryTextClass:w})]})]}),(0,t.jsxs)("div",{className:"tesla-card p-3 border border-hud bg-hud-bg",children:[(0,t.jsx)("div",{className:`text-xs font-black uppercase ${w} mb-3`,children:e("autopilot.sensitivity")}),(0,t.jsxs)("div",{className:"space-y-4",children:[(0,t.jsxs)("div",{children:[(0,t.jsxs)("div",{className:"flex justify-between mb-1",children:[(0,t.jsx)("span",{className:`text-xs font-bold ${N}`,children:e("autopilot.rudderSensitivity")}),(0,t.jsxs)("span",{className:`text-xs font-bold ${w}`,children:[F?.sensitivity?.rudder||50,"%"]})]}),(0,t.jsx)("input",{type:"range",min:"10",max:"100",value:F?.sensitivity?.rudder||50,onChange:e=>W({...F,sensitivity:{...F?.sensitivity,rudder:parseInt(e.target.value)}}),className:"w-full h-1.5 bg-hud-elevated rounded-full appearance-none cursor-pointer accent-oGreen"})]}),(0,t.jsxs)("div",{children:[(0,t.jsxs)("div",{className:"flex justify-between mb-1",children:[(0,t.jsx)("span",{className:`text-xs font-bold ${N}`,children:e("autopilot.deadZone")}),(0,t.jsxs)("span",{className:`text-xs font-bold ${w}`,children:[F?.sensitivity?.deadZone||10,"%"]})]}),(0,t.jsx)("input",{type:"range",min:"0",max:"30",value:F?.sensitivity?.deadZone||10,onChange:e=>W({...F,sensitivity:{...F?.sensitivity,deadZone:parseInt(e.target.value)}}),className:"w-full h-1.5 bg-hud-elevated rounded-full appearance-none cursor-pointer accent-oGreen"})]})]})]})]})},v)})})]})}let p=({label:e,button:s,onChange:o,primaryTextClass:n,secondaryTextClass:i})=>{let[l,d]=(0,a.useState)(!1);return(0,t.jsxs)("div",{className:"flex items-center justify-between py-2",children:[(0,t.jsx)("span",{className:`text-sm ${n}`,children:e}),l?(0,t.jsx)("select",{value:s,onChange:e=>{o(e.target.value),d(!1)},onBlur:()=>d(!1),autoFocus:!0,className:"bg-hud-elevated text-hud-main rounded px-2 py-1 text-sm border border-hud focus:border-oGreen/50 focus:outline-none transition-all",children:["X","Circle","Square","Triangle","L1","R1","L2","R2","D-Pad Up","D-Pad Down","D-Pad Left","D-Pad Right","Left Stick Up","Left Stick Down","Left Stick Left","Left Stick Right","Right Stick Up","Right Stick Down","Right Stick Left","Right Stick Right","L3","R3","Options","Share","PS"].map(e=>(0,t.jsx)("option",{value:e,children:e},e))}):(0,t.jsx)("button",{onClick:()=>d(!0),className:`px-3 py-1 bg-hud-elevated rounded text-sm ${i} hover:bg-hud-bg border border-hud transition-all`,children:s})]})};e.s(["default",()=>g])},33946,e=>{e.n(e.i(91440))}]);