From 773a788835503182af3901d65471e0e53e0f5a5f Mon Sep 17 00:00:00 2001 From: Determinant Date: Thu, 15 Aug 2024 17:57:27 -0700 Subject: ... --- ctrl.mjs | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----- profile.yaml | 34 +++++++++++++++--- xplane.mjs | 14 ++++---- 3 files changed, 139 insertions(+), 20 deletions(-) diff --git a/ctrl.mjs b/ctrl.mjs index 9ce1f8d..6c326f1 100755 --- a/ctrl.mjs +++ b/ctrl.mjs @@ -7,7 +7,7 @@ import { registerFont } from "canvas"; import { discover, HAPTIC } from "loupedeck"; import { readFile } from "fs/promises"; import { parse } from "yaml"; -import { sendCommand } from "./xplane.mjs"; +import { subscribeDataRef, sendCommand } from "./xplane.mjs"; const labelFont = "OCR A Extended"; const labelSize = 22; @@ -61,6 +61,8 @@ const rectifyLabel = (label) => { let text2 = null; let font2 = null; let size = labelSize; + let color_bg = null; + let color_fg = null; if (isObject(label)) { text = label.text; if (label.hasOwnProperty("size")) { @@ -70,14 +72,25 @@ const rectifyLabel = (label) => { text2 = label.text2; font2 = `${size * 0.9}px '${labelFont}'`; } + if (label.hasOwnProperty("color_bg")) { + color_bg = label.color_bg; + } + if (label.hasOwnProperty("color_fg")) { + color_fg = label.color_fg; + } } else { text = label.toString(); } let font = `${size}px '${labelFont}'`; - return { text, text2, font, font2 }; + return { text, text2, font, font2, color_bg, color_fg }; }; const drawKey = (key, label, down) => { + if (label && label.hasOwnProperty("display")) { + // not an input, but a display gauge + return; + } + device.drawKey(key, (c) => { const padding = 10; const bg = down ? "white" : "black"; @@ -152,7 +165,18 @@ const drawSideKnobs = (side, labels, highlight) => { h - y_padding * 2, ); if (labels && labels.length > i) { - const { text, font } = rectifyLabel(labels[i]); + const { text, font, color_bg, color_fg } = rectifyLabel( + labels[i], + ); + if (color_bg) { + c.fillStyle = color_bg; + c.fillRect( + x_padding + 2, + y_padding + y_offset + 2, + w - x_padding * 2 - 2, + h - y_padding * 2 - 2, + ); + } c.font = font; const { width, @@ -172,6 +196,74 @@ const drawSideKnobs = (side, labels, highlight) => { }); }; +const drawGauge = (key, label, value) => { + device.drawKey(key, (c) => { + const display = label.display; + const padding = 10; + const bg = "black"; + const fg = "white"; + const w = c.canvas.width; + const h = c.canvas.height; + + const min = display.min; + const max = display.max; + const stops = display.stops; + + if (isNaN(value)) { + value = 0; + } + let reading = (value - min) / max; + if (isNaN(reading)) { + reading = 0; + } + + const text = value.toString(); + + // draw background + c.fillStyle = bg; + c.fillRect(0, 0, w, h); + c.strokeStyle = fg; + c.lineWidth = 1; + const x0 = w / 2; + const y0 = h / 2 + 5; + const outer = 40; + const width = 5; + const inner = outer - width; + for (let i = 0; i < stops.length; i++) { + const theta0 = + Math.PI * (1 + (stops[i].value_begin - min) / max) + 0.05; + const theta1 = Math.PI * (1 + (stops[i].value_end - min) / max); + + c.beginPath(); + c.lineWidth = width; + c.strokeStyle = stops[i].color; + c.arc(x0, y0, outer - width / 2, theta0, theta1); + c.stroke(); + + c.beginPath(); + c.lineWidth = 2; + const cos = Math.cos(theta1); + const sin = Math.sin(theta1); + c.moveTo(x0 + cos * (inner - 2), y0 + sin * (inner - 2)); + c.lineTo(x0 + cos * (outer + 2), y0 + sin * (outer + 2)); + c.stroke(); + } + c.strokeStyle = fg; + c.lineWidth = 2; + c.beginPath(); + c.moveTo(x0, y0); + const theta = Math.PI * (1 + reading); + c.lineTo(x0 + Math.cos(theta) * inner, y0 + Math.sin(theta) * inner); + c.stroke(); + + const size = display.font ? display.font : labelSize; + c.font = `${size * 0.9}px '${labelFont}'`; + c.fillStyle = fg; + const m = c.measureText(text); + c.fillText(text, (w - m.width) / 2, h / 2 + 25); + }); +}; + const loadPage = (page) => { const { left, right, keys } = page || {}; if (!left) { @@ -180,11 +272,14 @@ const loadPage = (page) => { drawSideKnobs("left", left); drawSideKnobs("right", right); for (let i = 0; i < 12; i++) { - drawKey( - i, - Array.isArray(keys) && keys.length > i ? keys[i] : null, - false, - ); + const key = Array.isArray(keys) && keys.length > i ? keys[i] : null; + drawKey(i, key, false); + if (key && key.hasOwnProperty("display")) { + drawGauge(i, key, NaN); + if (key.display.hasOwnProperty("xplane_dataref")) { + subscribeDataRef(key.display.xplane_dataref); + } + } } }; diff --git a/profile.yaml b/profile.yaml index 506e173..e13daa3 100644 --- a/profile.yaml +++ b/profile.yaml @@ -2,24 +2,48 @@ # for xplane_cmd, refer to /Resources/plugins/Commands.txt under your X-Plane installation - left: - text: Thr. + inc: + xplane_cmd: sim/engines/throttle_up + dec: + xplane_cmd: sim/engines/throttle_down - text: Prop + color_bg: '#0000ff' - text: Mix. + inc: + xplane_cmd: sim/engines/mixture_up + dec: + xplane_cmd: sim/engines/mixture_down + color_bg: '#ff0000' keys: - - + - display: + xplane_dataref: sim/cockpit2/engine/indicators/MPR_in_hg + min: 0 + max: 3000 + stops: + - color: 'green' + value_begin: 500 + value_end: 2400 + - color: 'yellow' + value_begin: 2400 + value_end: 2700 + - color: 'red' + value_begin: 2700 + value_end: 3000 - - - text: Flap - text2: UP + text2: Up - - - - text: Flap - text2: T/O + text2: Down - - - - - text: Flap - text2: LDG + - text: Brake + pressed: + xplane_cmd: sim/flight_controls/brakes_toggle_regular # page 1 - left: diff --git a/xplane.mjs b/xplane.mjs index 7b82817..688f85f 100644 --- a/xplane.mjs +++ b/xplane.mjs @@ -4,11 +4,11 @@ const xplaneAddr = "localhost"; const xplanePort = 49000; const socket = dgram.createSocket("udp4"); -//socket.on('message', (msg, rinfo) => { -// console.log(msg, rinfo) -//}); -// -//socket.bind(10080); +socket.on("message", (msg, rinfo) => { + console.log(msg, rinfo); +}); + +socket.bind(10080); export const subscribeDataRef = async (dataRef) => { //const dataRef = "sim/flightmodel/position/indicated_airspeed"; @@ -19,7 +19,7 @@ export const subscribeDataRef = async (dataRef) => { off = buffer.writeInt32LE(0, off); // xint client off += buffer.write(dataRef, off); // char[400] dataref off = buffer.writeUInt8(0, off); // null terminated - console.log(Array.from(buffer)); + console.info(`x-plane dataref: ${dataRef}`); await socket.send(buffer, 0, buffer.length, xplanePort, xplaneAddr); }; @@ -33,4 +33,4 @@ export const sendCommand = async (cmd) => { await socket.send(buffer, 0, buffer.length, xplanePort, xplaneAddr); }; -//command("sim/GPS/g1000n1_hdg_down"); +//sendCommand("sim/GPS/g1000n1_hdg_down"); -- cgit v1.2.3-70-g09d2