-------------------------------------------------------------------- -- lib/ihm.lua : interfaces homme-machine. -- Display Link "conduite" : altitudes, vitesse, invites, alertes -- Display Link "carburant" : reserve + autonomie estimee (minutes) -- Advanced monitor tactile : modes (verrouilles si calibration -- manquante), consigne, calibrations, informations -- Typewriter : la saisie est geree dans drone.lua (scrutation) -------------------------------------------------------------------- local Ihm = {} function Ihm.nouveau(conf, materiel, journal) local ihm = {} local moniteur = materiel.moniteur moniteur.setTextScale(0.5) local zones = {} local messageConduite, messageFin = nil, 0 -- message temporaire sur la ligne 1 de la conduite (invites, -- alertes); duree en secondes (nil = 5) function ihm.message(texte, duree) messageConduite = texte messageFin = os.clock() + (duree or 5) end ------------------------------------------------------------------ -- ECRAN DE CONDUITE ------------------------------------------------------------------ -- ctx: { mode, consigneY, saisie } function ihm.rafraichirConduite(ctx) local e = materiel.ecranConduite e.clear() e.setCursorPos(1, 1) if messageConduite and os.clock() < messageFin then e.write(messageConduite:sub(1, 22)) elseif ctx.saisie and #ctx.saisie > 0 then e.write("SAISIE: " .. ctx.saisie) elseif ctx.mode == "vol" or ctx.mode == "drone" or ctx.mode == "atterrissage" or ctx.mode == "auto" or ctx.mode == "position" then e.write(("ALT %.1f / %.0f"):format( materiel.lireAltitude(), ctx.consigneY or 0)) else e.write("MODE " .. ctx.mode:upper()) end e.setCursorPos(1, 2) e.write(("VIT %.2f b/s"):format(materiel.vitesseHorizontale())) e.update() end ------------------------------------------------------------------ -- ECRAN CARBURANT (peut etre tres etroit: format compact) ------------------------------------------------------------------ -- pct 0..1 ou nil ; minutes ou nil function ihm.rafraichirCarburant(pct, minutes) local e = materiel.ecranCarburant local largeur = e.getSize() e.clear() e.setCursorPos(1, 1) if pct == nil then e.write(("n/a"):sub(1, largeur)) else e.write(("%d%%"):format(math.floor(pct * 100 + 0.5)):sub(1, largeur)) e.setCursorPos(1, 2) if minutes then e.write(("%dm"):format(math.floor(minutes)):sub(1, largeur)) else e.write(("--m"):sub(1, largeur)) end end e.update() end ------------------------------------------------------------------ -- MONITEUR TACTILE ------------------------------------------------------------------ local function bouton(x, y, texte, action, couleur) moniteur.setCursorPos(x, y) moniteur.setBackgroundColor(couleur or colors.gray) moniteur.write(" " .. texte .. " ") moniteur.setBackgroundColor(colors.black) table.insert(zones, { x1 = x, y1 = y, x2 = x + #texte + 1, y2 = y, action = action, }) end local function texte(x, y, contenu, couleur) moniteur.setTextColor(couleur or colors.white) moniteur.setCursorPos(x, y) moniteur.write(contenu) moniteur.setTextColor(colors.white) end -- ctx: { mode, consigneY, stress, position, carburantPct, minutes, -- moteurOk, verrous = { mode -> raison|nil }, points = n } function ihm.rafraichirMoniteur(ctx) zones = {} moniteur.setBackgroundColor(colors.black) moniteur.clear() texte(1, 1, "== MODES == actuel: " .. ctx.mode) local modes = { "off", "inactif", "stationnement", "vol", "drone", "atterrissage", "auto", "position" } local x, y = 1, 2 for _, m in ipairs(modes) do local verrou = ctx.verrous[m] local couleur = colors.gray if m == ctx.mode then couleur = colors.green elseif verrou then couleur = colors.red end if x + #m + 2 > 50 then x, y = 1, y + 1 end bouton(x, y, m, { type = "mode", valeur = m, verrou = verrou }, couleur) x = x + #m + 3 end texte(1, y + 2, ("== CONSIGNE == %.0f"):format(ctx.consigneY or 0)) bouton(1, y + 3, "-10", { type = "delta", valeur = -10 }) bouton(7, y + 3, "-1", { type = "delta", valeur = -1 }) bouton(12, y + 3, "+1", { type = "delta", valeur = 1 }) bouton(17, y + 3, "+10", { type = "delta", valeur = 10 }) texte(1, y + 5, "== CALIBRATIONS ==") local cx = 1 for _, c in ipairs({ "gimbal", "joystick", "typew", "rsc", "capteurs", "pid" }) do bouton(cx, y + 6, c, { type = "calib", valeur = c }) cx = cx + #c + 3 end local ly = y + 8 texte(1, ly, "== INFOS ==") local t, r = materiel.lireAssiette() texte(1, ly + 1, ("assiette T %+.2f R %+.2f%s"):format(t, r, ctx.gimbalOk and "" or " (NON CALIBRE)")) texte(1, ly + 2, ("sol %.1f (%s%s)"):format( materiel.lireDistanceSol(), materiel.auSol() and "au sol" or "en vol", materiel.solPosable() and "" or ", NON POSABLE")) texte(1, ly + 3, ("stress %s moteur %s"):format( ctx.stress and ("%.0f%%"):format(ctx.stress * 100) or "n/a", ctx.moteurOk and "ok" or "ARRETE"), ctx.moteurOk and colors.white or colors.red) texte(1, ly + 4, ("carburant %s autonomie %s"):format( ctx.carburantPct and ("%.0f%%"):format(ctx.carburantPct * 100) or "n/a", ctx.minutes and ("%dmin"):format(math.floor(ctx.minutes)) or "--")) if ctx.position then texte(1, ly + 5, ("gps %.0f %.0f %.0f points: %d") :format(ctx.position.x, ctx.position.y, ctx.position.z, ctx.points or 0)) else texte(1, ly + 5, "gps n/a", colors.red) end end function ihm.traiterToucher(tx, ty) for _, z in ipairs(zones) do if tx >= z.x1 and tx <= z.x2 and ty >= z.y1 and ty <= z.y2 then return z.action end end return nil end -- attend un toucher du moniteur (utilise par les calibrations) function ihm.attendreToucher() while true do local ev = os.pullEvent("monitor_touch") if ev then return end end end return ihm end return Ihm