-- ########################################################################################################################################################## -- # Display Color App # -- # Lua app für JETI Sender mit Farbdisplay # -- ########################################################################################################################################################## -- ########################################################################################################################################################## -- # # -- # MIT License # -- # # -- # # -- # Copyright (c) 2025 IG-Development Ingmar Grote # -- # Email: i.grote@i-g.de # -- # ------------------------------------------------------------------------------------------------------------------------------------------------------ # -- # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), # -- # I to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, # -- # and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: # -- # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. # -- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # -- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, # -- # DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE # -- # USE OR OTHER DEALINGS IN THE SOFTWARE. # -- # ------------------------------------------------------------------------------------------------------------------------------------------------------ # -- # Sinngemäße Übersetzung (nicht offiziell) # -- # Jedem, der eine Kopie dieser Software und der zugehörigen Dokumentationsdateien (die "Software") erhält, wird hiermit kostenlos die Erlaubnis erteilt, # -- # ohne Einschränkung mit der Software zu handeln, einschließlich und ohne Einschränkung der Rechte zur Nutzung, zum Kopieren, ändern, Zusammenführen, # -- # Veröffentlichen, Verteilen, Unterlizenzieren und/oder Verkaufen von Kopien der Software, und Personen, denen die Software zur Verfügung gestellt wird, # -- # dies unter den folgenden Bedingungen zu gestatten: # -- # Der obige Urheberrechtshinweis und dieser Genehmigungshinweis müssen in allen Kopien oder wesentlichen Teilen der Software enthalten sein. # -- # DIE SOFTWARE WIRD OHNE MÄNGELGEWÄHR UND OHNE JEGLICHE AUSDRÜCKLICHE ODER STILLSCHWEIGENDE GEWÄHRLEISTUNG, EINSCHLIESSLICH, ABER NICHT BESCHRÄNKT AUF # -- # DIE GEWÄHRLEISTUNG DER MARKTGÄNGIGKEIT, DER EIGNUNG FÜR EINEN BESTIMMTEN ZWECK UND DER NICHTVERLETZUNG VON RECHTEN DRITTER, ZUR VERFÜGUNG GESTELLT. # -- # DIE AUTOREN ODER URHEBERRECHTSINHABER SIND IN KEINEM FALL HAFTBAR FÜR ANSPRÜCHE, SCHÄDEN ODER ANDERE VERPFLICHTUNGEN, OB IN EINER VERTRAGS- ODER # -- # HAFTUNGSKLAGE, EINER UNERLAUBTEN HANDLUNG ODER ANDERWEITIG, DIE SICH AUS, AUS ODER IN VERBINDUNG MIT DER SOFTWARE ODER DER NUTZUNG ODER ANDEREN # -- # GESCHÄFTEN MIT DER SOFTWARE ERGEBEN. # -- # # -- ########################################################################################################################################################## -- ########################################################################################################################################################## -- ########################################################################################################################################################## -- ## ## -- ## !!!!!!!! ACHTUNG !!!!!!!! ## -- ## JETI weist ausdrücklich darauf hin, Lua-Anwendungen nicht zur Steuerung von Modellfunktionen zu verwenden, welche einen Absturz verursachen können, ## -- ## wenn sich die Anwendung nicht richtig verhält oder nicht mehr ausgeführt wird. ## -- ## ---------------------------------------------------------------------------------------------------------------------------------------------------- ## -- ## Hier der Originaltext aus der JETI DCDS_Lua_API_1.5: ## -- ## WARNING ## -- ## Do not use Lua applications for controlling any model function that could cause a crash if the application misbehaves or stops executing. ## -- ## ---------------------------------------------------------------------------------------------------------------------------------------------------- ## -- ## Bitte beachten sie obenstehende Warnhinweise! ## -- ## ## -- ########################################################################################################################################################## -- ########################################################################################################################################################## collectgarbage() --[[one -- nach unbeabsichtigten globalen Variablen suchen setmetatable(_G, { __newindex = function(array, key, value) print(string.format("Changed _G: %s = %s", tostring(key), tostring(value))); rawset(array, key, value); end }); --]] local trans, formID, filesSave, filesLoad, sensors, sensorsMax, tiles, methods, methodsMax, params, values, limits, positions, counts, filesImage, alert, batteryAlert, engine, SnapShot, switchTiles, image, logo, battery, indexLoad, spacers, flightDone, flightTime, flightLast, options, ids, names, name, background, imageWarning, indices, colors, heights, heightMax local timeVars = { eTime = 0, fTime = 0, cTime = 0, bTime = 0, qTime1 = 0, a1Time1 = 0, a2Time1 = 0, qTime2 = 0, a1Time2 = 0, a2Time2 = 0, qTimeB = 0, a1TimeB = 0, a2TimeB = 0, eLastTime = 0, fLastTime = 0, cLastTime = 0, timeModel, B4 = nil, B5 = nil } local timeHMS = {} timeHMS.fHrs = 0 timeHMS.fMin = 0 timeHMS.fSec = 0 timeHMS.eMin = 0 timeHMS.eSec = 0 timeHMS.cMin = 0 timeHMS.cSec = 0 timeHMS.bMin = 0 timeHMS.bSec = 0 local bTimerBeepRuns = false local lastAn3, lastAn4, lastAlert = 0, 0, 0 local paramsMax, positionsMax, positionMax, battMax, timeAlert, val, minval, maxval = 6, 12, 12, 20, 3000, 0, 100, 0 local sw, se, ka, rx = {}, {}, {}, {count=12, alert=10} local dDimg = {} local folder, extensionFile, folderJsn, extensionJsonFile, extensionsImage = "Apps/Display-HI/", ".txt", "Apps/Display-HI/JSN/", ".jsn", {".png", ".jpg"} -- Achtung: Im Versionsstring darf kein Leerzeichen enthalten sein. local metaData = { AppName = "Display-HI Color", Version = "7.1.0d", Authors = "IG-Development Ingmar Grote + theTall Holger Ahmels", AuthorsShort = "Holger & Ingmar", Pilot = system.getUserName("name"), Model = system.getProperty("Model"), ModelFileName = system.getProperty("ModelFile"), SaveDate = "", DataStorage = { modelfile = nil, fileForSave = "DApp_"..system.getProperty("Model")..extensionJsonFile, -- Vom Benutzer ist der Name änderbar ohne Prefix und Extension fileForLoad = "" -- Aus einer Liste auswählbar } } local jsnModelFile = nil -- Standarddatei, wird einmal pro Modell vergeben mit eindeutiger ID local bShowColorByPrintForm = false local RGB1, RGB2, RGB3, RGB4 = 255, 255, 255, 255 local RGBbg local RGBsema = false local variables = { bCmdSaveSettings = false,-- Wenn gespeichert werden muß --> true bCmdLoadSettings = true, -- Wenn geladen werden muß --> true fileLoadList = nil, -- Liste der Dateien zum Daten speichern und laden durch Auswahl vom Piloten Collect = {} -- Einzelne Variablen gesammelt } --Max. 200 local variables! local ACC_OF_FLEXPICS = 6 -- Größe des FlexPic-Feldes, Anzahl aller vorhandener Flexpic-Instanzen local iActFlexPic = 1 local FlexPics = { iAccOfFlexPic = ACC_OF_FLEXPICS, -- Anzahl aller vorhandener FlexPic-Instanzen iActFlexPicProj = 1, -- Merker für die zuletzt projektierte Kachel iFlexPicIdx1 = { }, iFlexPicIdx2 = { }, iFlexPicIdx3 = { }, iFlexPicIdx4 = { }, iFlexPicIdx5 = { }, iFlexPicIdx6 = { } } -- Parameter aller TeleValues initialisieren for i=1, FlexPics.iAccOfFlexPic do local Idx Idx = string.format("iFlexPicIdx%d", i) FlexPics[Idx].iFlexPicNo = i FlexPics[Idx].swFlexPic = nil -- Schalter/Geber muß speziell in JSN-File gespeichert werden FlexPics[Idx].sFlexPicName = string.format("FlexPic%02d", i) FlexPics[Idx].sFlexPicHeader = "" FlexPics[Idx].sFlexPicFileName1 = "EmptyPic" FlexPics[Idx].iFlexPicFileIndex1 = 1 FlexPics[Idx].imgFlexPic1 = nil -- temporärer Pointer, darf nicht in JSN-File gespeichert werden FlexPics[Idx].bFlexPicChanged1 = true FlexPics[Idx].sFlexPicFileName2 = "EmptyPic" FlexPics[Idx].iFlexPicFileIndex2 = 1 FlexPics[Idx].imgFlexPic2 = nil FlexPics[Idx].bFlexPicChanged2 = true FlexPics[Idx].sFlexPicFileName3 = "EmptyPic" FlexPics[Idx].iFlexPicFileIndex3 = 1 FlexPics[Idx].imgFlexPic3 = nil FlexPics[Idx].bFlexPicChanged3 = true FlexPics[Idx].iFlexPicLastSelectedIndex = 1 FlexPics[Idx].iFlexPicHeight = 38 FlexPics[Idx].iFlexPicBgColor = 0 FlexPics[Idx].iFlexPicAllignmentHorizontal = 2 FlexPics[Idx].iFlexPicAllignmentVertikal = 1 FlexPics[Idx].fFlexPicLim12 = -49.0 FlexPics[Idx].fFlexPicLim23 = 51.0 FlexPics[Idx].fFlexPicLim32 = 49.0 FlexPics[Idx].fFlexPicLim21 = -51.0 FlexPics[Idx].fFlexPicValue = 0.0 FlexPics[Idx].iFlexPicState = 0 end local ACC_OF_TELEVALUES = 24 -- Größe des TeleValue-Feldes, Anzahl aller vorhandener TelVal-Instanzen local iActTelVal = 1 local TelVal = { Sensors = {}, -- Liste aller Sensoren und Parameter aus dem Systemaufruf SensorListLabel = {"..."}, -- Liste der vorhandenen Sensoren; Name oder Label des Sensors mit angehängter ID zur eindeutigen Identifizierung SensorListId = {0}, -- Liste der vorhandenen Sensoren; Eindeutige ID des Sensors SensorListIdx = {0}, -- Liste der vorhandenen Sensoren; Eindeutiger Index des Sensors im Feld aller Sensoren SensorListType = {0}, -- Liste der Sensortypen: 1=Empfängersensor; 2=Sendersensor (Calca-App, Timer, Zähler, etc.) -- Derzeit sind Listen für 16 verschiedene Sensoren vorgesehen, erster Wert ist der NULL-Wert SensorListWertLabel1 = {"..."}, -- Liste der Telemetriewerte aller vorhandener Sensoren (16 Felder) SensorListWertLabelIdx1 = {0}, -- Liste der Telemetriewert-Indizes des ausgewählten Sensors im Feld aller Sensoren (16 Felder) SensorListWertLabel2 = {"..."}, SensorListWertLabelIdx2 = {0}, SensorListWertLabel3 = {"..."}, SensorListWertLabelIdx3 = {0}, SensorListWertLabel4 = {"..."}, SensorListWertLabelIdx4 = {0}, SensorListWertLabel5 = {"..."}, SensorListWertLabelIdx5 = {0}, SensorListWertLabel6 = {"..."}, SensorListWertLabelIdx6 = {0}, SensorListWertLabel7 = {"..."}, SensorListWertLabelIdx7 = {0}, SensorListWertLabel8 = {"..."}, SensorListWertLabelIdx8 = {0}, SensorListWertLabel9 = {"..."}, SensorListWertLabelIdx9 = {0}, SensorListWertLabel10 = {"..."}, SensorListWertLabelIdx10 = {0}, iMaxAccOfSensorListEntries = 10, --[[ erstmal auskommentiert, da so viele Sensoren meistens nicht vorhanden sind. SensorListWertLabel11 = {"..."}, SensorListWertLabelIdx11 = {0}, SensorListWertLabel12 = {"..."}, SensorListWertLabelIdx12 = {0}, SensorListWertLabel13 = {"..."}, SensorListWertLabelIdx13 = {0}, SensorListWertLabel14 = {"..."}, SensorListWertLabelIdx14 = {0}, SensorListWertLabel15 = {"..."}, SensorListWertLabelIdx15 = {0}, SensorListWertLabel16 = {"..."}, SensorListWertLabelIdx16 = {0}, --]] bCalcaAppActive = false, iStateMachineLoad = 0, iREXoffset = 0, -- Ermittelter Offset für die REX-Sensorwerte iAccOfTelVal = ACC_OF_TELEVALUES, iActTelValProj = 1, -- Merker für die zuletzt projektierte Kachel -- Es folgen die Parameter der einzelnen TelValinstanzen iTVInst1 = { }, iTVInst2 = { }, iTVInst3 = { }, iTVInst4 = { }, iTVInst5 = { }, iTVInst6 = { }, iTVInst7 = { }, iTVInst8 = { }, iTVInst9 = { }, iTVInst10 = { }, iTVInst11 = { }, iTVInst12 = { }, iTVInst13 = { }, iTVInst14 = { }, iTVInst15 = { }, iTVInst16 = { }, iTVInst17 = { }, iTVInst18 = { }, iTVInst19 = { }, iTVInst20 = { }, iTVInst21 = { }, iTVInst22 = { }, iTVInst23 = { }, iTVInst24 = { } } -- Parameter aller TeleValues initialisieren for i=1, ACC_OF_TELEVALUES do local Idx Idx = string.format("iTVInst%d", i) TelVal[Idx].iTelValNo = i TelVal[Idx].sTelValName = string.format("TeleValue%02d", i) TelVal[Idx].sTelValHeader = "" TelVal[Idx].iTelValAllignmentHorizontal = 3 TelVal[Idx].iTelValSize = 2 -- Default Kachelgröße 1=mini, 2=normal, 3=big TelVal[Idx].swTelVal = nil TelVal[Idx].bSemaPlay = false -- Initwert Sound nicht wierholt ausgeben, nur einmal TelVal[Idx].swValPlay = nil -- Taster/Schalter löst Ansage aus TelVal[Idx].bCommandPlay = false -- Kommando zum Einstellen der Sounddatei in die Audioque TelVal[Idx].iLockNewPlay = 0 -- Pause, damit bei Signalschwankungen nicht ständig neue Files in die Audioschlange eingetragen werden. =0 -> freigegeben, >0 -> gesperrt TelVal[Idx].sTelValSensor = "" TelVal[Idx].iTelValSensorID = 0 TelVal[Idx].iTelValSensorNo = 1 TelVal[Idx].iTelValSensorIdx = 1 TelVal[Idx].iTelValSensorType = 1 -- Liste der Sensortypen: 1=Empfängersensor; 2=Sendersensor (Calca-App, Timer, Zähler, etc.) TelVal[Idx].bTelValSensorNoName = false -- false = Sensor hat einen Namen TelVal[Idx].sTelValParam = "" TelVal[Idx].iTelValParamNo = 1 -- Index im Sensorwertefeld sensorbezogen TelVal[Idx].iTelValParamIdx = 1 -- Index im kompletten Sensorfeld TelVal[Idx].sTelValEinheit = " ?" TelVal[Idx].sTelValKorrekturfaktor = "1.0" TelVal[Idx].iTelValNachkomma = 1 TelVal[Idx].fTelValAct = 0.0 TelVal[Idx].fTelValMin = 0.0 TelVal[Idx].fTelValMax = 0.0 TelVal[Idx].sTelValActText = "" TelVal[Idx].fLimGrowWarning = nil TelVal[Idx].fLimGrowAlarm = nil TelVal[Idx].fLimShrkWarning = nil TelVal[Idx].fLimShrkAlarm = nil TelVal[Idx].iLimBlinken = 0 -- 0= kein Blinken TelVal[Idx].iLimBlinkenFreqZael = 6 -- Zahler n-Zyklen dann andere Farbe (30 im Emulator, 6 im Sender) TelVal[Idx].iTelValHeight = 36 TelVal[Idx].iTelValWidth = 128 TelVal[Idx].iTelValBgColor = 0 TelVal[Idx].iTelValTxColor = nil TelVal[Idx].iTelValBgColorMem = nil TelVal[Idx].fTVTxLim1 = nil TelVal[Idx].fTVTxLim2 = nil TelVal[Idx].fTVTxLim3 = nil TelVal[Idx].fTVTxLim4 = nil TelVal[Idx].sTVTxText1 = "" TelVal[Idx].sTVTxText2 = "" TelVal[Idx].sTVTxText3 = "" TelVal[Idx].sTVTxText4 = "" TelVal[Idx].bTVSmooth = false TelVal[Idx].fValueFieldSmooth = {2, 0.0, 0.0, 0.0, 0.0} -- Die Funktion Smothing(tv, actValue) paßt sich der Speichergröße (Glättung) an end -- Die Hintergrundfarben individuell vorbelegen, siehe Doku-Farbtabelle TelVal.iTVInst1.iTelValBgColor = 13 TelVal.iTVInst2.iTelValBgColor = 29 TelVal.iTVInst3.iTelValBgColor = 32 TelVal.iTVInst4.iTelValBgColor = 35 TelVal.iTVInst5.iTelValBgColor = 14 TelVal.iTVInst6.iTelValBgColor = 10 TelVal.iTVInst7.iTelValBgColor = 14 TelVal.iTVInst8.iTelValBgColor = 15 TelVal.iTVInst9.iTelValBgColor = 22 TelVal.iTVInst10.iTelValBgColor = 25 TelVal.iTVInst11.iTelValBgColor = 28 TelVal.iTVInst12.iTelValBgColor = 31 TelVal.iTVInst13.iTelValBgColor = 34 TelVal.iTVInst14.iTelValBgColor = 37 TelVal.iTVInst15.iTelValBgColor = 40 TelVal.iTVInst16.iTelValBgColor = 1 TelVal.iTVInst17.iTelValBgColor = 2 TelVal.iTVInst18.iTelValBgColor = 3 TelVal.iTVInst19.iTelValBgColor = 4 TelVal.iTVInst20.iTelValBgColor = 5 TelVal.iTVInst21.iTelValBgColor = 6 TelVal.iTVInst22.iTelValBgColor = 7 TelVal.iTVInst23.iTelValBgColor = 8 TelVal.iTVInst24.iTelValBgColor = 9 local SpecTiles = { calcaElec = nil, calcaPlus = nil, calcaFuel = nil, OpAccHour = nil, -- Es folgen die Parameter der einzelnen Spezial-Kacheln AkkuTank = { iAccOfStorage = 1, -- Default und Initwert sSensorName1 = "...", iSensorNo1 = 1, iSensorId1 = 0, sSensorValueName1 = "...", iSensorValueNo1 = 1, iSensorValueIdx1= 1, iSensorType1 = 1, sSensorUnit1 = " ", sKorrekturfaktor1 = "1.0", bConvertGrowToShrk1 = false, iConvGtoScapacity1 = 100, -- Alter Wert bevor Umschaltung auf 100% Wert iCapacity1 = 100, -- Wert in %, mAh, ml, etc. = Maximalwert des Sensorwertes iMaxBarValue1 = 100, -- maximaler Wert des Balkens (meistens 100 [%]) fValueAct1 = 0.0, -- Initwert iWarningValue1 = 30, -- % iAlarmValue1 = 18, -- % sWarningSound1 = "...",-- Dateiname Soundfiles1 sAlarmSound1 = "...",-- Dateiname Soundfiles1 bWarningSend1 = true, -- Initwert bAlarmSend1 = true, -- Initwert bCommandPlay1 = false, -- Kommando zum Einstellen der Sounddatei in die Audioque iLockNewPlay1 = 0, -- Pause, damit bei Signalschwankungen nicht ständig neue Files in die Audioschlange eingetragen werden. =0 -> freigegeben, >0 -> gesperrt bSemaPlay1 = false,-- Initwert swValPlay1 = nil, sRepresentation1= "2000", -- Beschriftung Fußzeile sRepresentUnit1 = "mAh",-- Beschriftung Fußzeile Einheit bGrowing1 = false,-- = true Wachsend von unten nach oben; false (Default) von oben nach unten sSensorName2 = "...", iSensorNo2 = 1, iSensorId2 = 0, sSensorValueName2 = "...", iSensorValueNo2 = 1, iSensorValueIdx2= 1, iSensorType2 = 1, sSensorUnit2 = " ", sKorrekturfaktor2 = "1.0", bConvertGrowToShrk2 = false, iConvGtoScapacity2 = 2000, iCapacity2 = 2000, iMaxBarValue2 = 100, fValueAct2 = 0.0, iWarningValue2 = 180, iAlarmValue2 = 160, sWarningSound2 = "...", sAlarmSound2 = "...", bWarningSend2 = true, bAlarmSend2 = true, bCommandPlay2 = false, iLockNewPlay2 = 0, bSemaPlay2 = false, swValPlay2 = nil, sRepresentation2= "2000", sRepresentUnit2 = "mAh", bGrowing2 = true, bShowScale = true, bAnsageRestmenge= true, iTilesHeigtht = 155, sPicFileName = "EmptyPic", iPicFileIndex = 1, imgPicFile = nil, bPicFileChanged = false, iBgColor = 0, iTransparenz = 180, sTxColDrawNo = "Black" } } -- Daten für die Oszilloskop Kachel -- -------------------------------- -- Oszilloskop -- -- Start-, Stopp- und Resetschalter für das Oszilloskop sw.OsziStartSw = nil sw.OsziStoppSw = nil sw.OsziResetSw = nil sw.OsziSaveSw = nil sw.OsziLoadSw = nil sw.OsziOneShotSw = nil local Oszi = {} Oszi.Data = {} -- Datenspeicher Oszi.Data.oTime = nil -- Sollzeit wann die nächste Abtastung erreicht ist, =nil --> läuft nicht Oszi.Data.Values = {} Oszi.Data.Values.AccOfChannels = 4 -- 4 Kanäle, falls mehr gewünscht, Speicher und Performanz prüfen Oszi.Data.Values.T = 100 -- Abtastzeit in ms Oszi.Data.Values.maxTime = 10000 -- Eingestellte Zeitspanne auf der X-Achse Oszi.Data.Values.Ch1 = {} -- Neuer Kanal Oszi.Data.Values.Ch1.TVpointer = nil -- Nummer des TeleValues, das darzustellen ist (1 - 24) Oszi.Data.Values.Ch1.maxValue = 1 -- maximaler physikalischer Wert zur Normierung Oszi.Data.Values.Ch1.Header = " " -- Überschrift des Wertes zur Anzeige in der Legende Oszi.Data.Values.Ch1.Unit = " " -- Einheit des Wertes zur Anzeige in der Legende Oszi.Data.Values.Ch1.LnCol = 43 -- Linienfarbe des Kanals Oszi.Data.Values.Ch1.Point = {} -- Wertespeicher Oszi.Data.Values.Ch1.Time = {} -- Zeitstempel Oszi.Data.Values.Ch2 = {} Oszi.Data.Values.Ch2.TVpointer = nil Oszi.Data.Values.Ch2.maxValue = 1 Oszi.Data.Values.Ch2.Header = " " Oszi.Data.Values.Ch2.Unit = " " Oszi.Data.Values.Ch2.LnCol = 43 Oszi.Data.Values.Ch2.Point = {} Oszi.Data.Values.Ch2.Time = {} Oszi.Data.Values.Ch3 = {} Oszi.Data.Values.Ch3.TVpointer = nil Oszi.Data.Values.Ch3.maxValue = 1 Oszi.Data.Values.Ch3.Header = " " Oszi.Data.Values.Ch3.Unit = " " Oszi.Data.Values.Ch3.LnCol = 43 Oszi.Data.Values.Ch3.Point = {} Oszi.Data.Values.Ch3.Time = {} Oszi.Data.Values.Ch4 = {} Oszi.Data.Values.Ch4.TVpointer = nil Oszi.Data.Values.Ch4.maxValue = 1 Oszi.Data.Values.Ch4.Header = " " Oszi.Data.Values.Ch4.Unit = " " Oszi.Data.Values.Ch4.LnCol = 43 Oszi.Data.Values.Ch4.Point = {} Oszi.Data.Values.Ch4.Time = {} Oszi.Data.Values.sStoppText = "" Oszi.Graph = {} -- Graphikanzeige Oszi.Graph.Width = 314 -- Kachelbreite Oszi.Graph.Height = 110 -- Kachelhöhe Oszi.Graph.AxisDistant = 5 -- Pixelabstand zu den Kachelrändern Oszi.Graph.ArrowSize = 6 -- Pfeilgröße in Pixel; =0 keine Pfeilspitze Oszi.Graph.posXaxis = 2 -- 1= oben, 2= mitte, 3= unten Oszi.Graph.BgCol = 7 -- Hintergrundfarbe der Kachel Oszi.Graph.Legend = {} Oszi.Graph.Legend.xPosTx = 20 -- Immer das erste Feldelement setzen Oszi.Graph.Legend.yPosTx = 1 Oszi.Graph.Legend.Gitter = true Oszi.Graph.Legend.xPosTxTime = Oszi.Graph.Width - 20 Oszi.Graph.Legend.yPosTxTime = Oszi.Graph.Height - 20 Oszi.Graph.Legend.TextTime = "t[sec]" Oszi.Graph.Legend.bStoppWritten = false Oszi.Save = {} -- Test zum Speichern der gestoppten Daten Oszi.Save.Name = " " Oszi.Save.Date = " " Oszi.Save.StopTime = " " Oszi.Save.oShotTime = nil -- Sollzeit wann das Ende des OneShot erreicht ist, =nil --> läuft nicht Oszi.Save.Values = {} Oszi.Semaphoren = {} -- Verriegelungen z.B. für Schalter/Taster Oszi.Semaphoren.Save = true -- Das Speichern ist freigegeben Oszi.Semaphoren.Load = true -- Das Laden ist freigegeben Oszi.Semaphoren.OneShot = false -- Der OneShot läuft nicht -- Initialisierung der Oszi.TVlist-Tabelle zur Auswahl der TeleValue-Datenquellen Oszi.TVlist = {} Oszi.TVlist[1] = "..." for i=2, ACC_OF_TELEVALUES + 1 do Oszi.TVlist[i] = string.format("TeleValue%d", i-1) end local sFirmware = system.getVersion() if (sFirmware == "6.03") or (sFirmware >= "6.05") then SpecTiles.calcaElec = gCalcaElec SpecTiles.calcaPlus = gCalcaPlus SpecTiles.calcaFuel = gCalcaFuel SpecTiles.OpAccHour = gOpAccHour else SpecTiles.calcaElec = _G["calca-Elec_G"] SpecTiles.calcaPlus = _G["calca-Plus_G"] SpecTiles.calcaFuel = _G["calca-Fuel_G"] SpecTiles.OpAccHour = _G["OpAccHour_G"] end local function ResetOsziData() -- Diese Funktion löscht die Datenfelder der 4 Kanäle des Oszilloskops local ov = Oszi.Data.Values -- Absicherung if (ov.maxTime == nil) or (ov.T == nil) or (ov.AccOfChannels == nil)then -- Standardwerte ov.maxTime = 10000 -- 10 Sekunden ov.T = 100 -- 100 ms ov.AccOfChannels = 4 end local AccOfPoints = ov.maxTime / ov.T local Idx, Id for j=1, ov.AccOfChannels do Idx = string.format("Ch%d", j) if ov[Idx].Point == nil then ov[Idx].Point = {} -- Feld neu anlegen end if ov[Idx].Time == nil then ov[Idx].Time = {} -- Feld neu anlegen end for i=1, AccOfPoints do ov[Idx].Point[i] = 0.0 ov[Idx].Time[i] = 0.0 end end Oszi.TVlist = nil Oszi.TVlist = {} -- Initialisierung der Oszi.TVlist-Tabelle Oszi.TVlist[1] = "..." for i=2, ACC_OF_TELEVALUES + 1 do Oszi.TVlist[i] = string.format("TeleValue%d", i-1) end Oszi.Save = {} Oszi.Save.Name = " " Oszi.Save.Date = " " Oszi.Save.StopTime = " " Oszi.Data.Values.sStoppText = "" Oszi.Semaphoren = {} Oszi.Semaphoren.Save = true -- Das Speichern ist freigegeben Oszi.Semaphoren.Load = true -- Das Laden ist freigegeben Oszi.Semaphoren.OneShot = false -- Der OneShot läuft nicht Oszi.Save.Values = {} end -- Read translations local function setLanguage() local name = "strings" local extension = extensionJsonFile local locale = "-"..system.getLocale() local file = io.readall(folder..name..locale..extension) if (not file) then file = io.readall(folder..name..extension) end trans = json.decode(file) -- nach fehlenden Einträgen in Sprachtextdateien (jsn-Dateityp) suchen --[[ print("pruefe strings...") local charsName = #name local charsExtension = #extension local emulator = select(2, system.getDeviceType()) local array = {} if (emulator == 0) then folder = "/"..folder:sub(1, -2) end for entryName, entryType in dir(folder) do if (entryType == "file") then local entryLocale = entryName:match(name.."%-*([^%.]*)"..extension) if (entryLocale) then local entryFile = io.readall(folder..entryName) print("lade Sprachdatei: "..folder..entryName) local entryTrans = json.decode(entryFile) array[entryLocale] = entryTrans end end end local text = "%s aber nicht %s: %s" local lang1 = "de" local array1 = array[lang1] for lang2, array2 in pairs(array) do if (lang1 ~= lang2) then for key in pairs(array1) do if (not array2[key]) then print(string.format(text, lang1, lang2, key)) end end for key in pairs(array2) do if (not array1[key]) then print(string.format(text, lang2, lang1, key)) end end end end print("fertig") --]] end local function drawKaBackground(x, y, width, height) --if(true) then --Frames if(variables.Collect.framed) then --Frames if((width > 8) and (height > 8)) then lcd.drawRectangle (x, y, width, height, 3) else lcd.drawRectangle (x, y, width, height, 0) --lcd.drawFilledRectangle(x, y, width, height) end else lcd.drawFilledRectangle(x, y, width, height) end end -- Die Höhen der Kacheln müssen nach Änderung oder Laden der Settings neu gesetzt werden. local function UpdateHeights() heights = { 0 } for idx=1, 15 do local Idx = string.format("iTVInst%d", idx) local tv = TelVal[Idx] heights[idx+1] = tv.iTelValHeight end heights[17] = 22 heights[18] = 31 heights[19] = 52 heights[20] = 43 for idx=1, 6 do local Idx = string.format("iFlexPicIdx%d", idx) local fp = FlexPics[Idx] heights[20+idx] = fp.iFlexPicHeight end heights[27] = SpecTiles.AkkuTank.iTilesHeigtht heights[28] = 31 heights[29] = 22 heights[30] = 31 heights[31] = 22 -- Um 9 TeleValues erweitert for idx=16, ACC_OF_TELEVALUES do local Idx = string.format("iTVInst%d", idx) local tv = TelVal[Idx] heights[32-16+idx] = tv.iTelValHeight end heights[41] = Oszi.Graph.Height end local function setColors() local name = "colors" local extension = extensionJsonFile local file = io.readall(folder..name..extension) colors = json.decode(file) end local function changeColorByIndex(i,trans) -- Keine Hintergrundfarbe bei i==0 if (i ~= nil) then if( (i >= 1) and (i<=44) )then local sColNo = string.format("color%02d", i) local sRGB = colors[sColNo] local red = tonumber(string.sub(sRGB,1,3)) local green = tonumber(string.sub(sRGB,4,6)) local blue = tonumber(string.sub(sRGB,7,9)) RGB1 = red RGB2 = green RGB3 = blue RGB4 = trans RGBbg = i lcd.setColor(red,green,blue,trans) elseif( (i<0) and (i>44) )then print("changeColorByIndex("..i..") Fehler: falscher Index") elseif i==0 then RGB1 = 255 RGB2 = 255 RGB3 = 255 RGB4 = 255 RGBbg = i end else RGB1 = 255 RGB2 = 255 RGB3 = 255 RGB4 = 255 RGBbg = 0 end end local iSchriftTab = {} for i=1, 44 do iSchriftTab[i] = 0 -- 0= schwarz/dunkele Schrift; 1= weiß/helle Schrift end -- Es folgen die Schriftfarben, die in weiß geschrieben werden iSchriftTab[3] = 1 iSchriftTab[5] = 1 iSchriftTab[6] = 1 iSchriftTab[12] = 1 iSchriftTab[15] = 1 iSchriftTab[18] = 1 iSchriftTab[20] = 1 iSchriftTab[21] = 1 iSchriftTab[23] = 1 iSchriftTab[24] = 1 iSchriftTab[27] = 1 iSchriftTab[30] = 1 iSchriftTab[33] = 1 iSchriftTab[35] = 1 iSchriftTab[36] = 1 iSchriftTab[38] = 1 iSchriftTab[39] = 1 iSchriftTab[41] = 1 iSchriftTab[42] = 1 iSchriftTab[43] = 1 -- Einstellung der Textfarbe in Abhängigkeit der Hintergrundfarbe local function setTextColorDependBG(txCol, trans, bgCol) local sColorDependBG = "Black" -- Default für die großen Zeichensätze "drawNumber()" if bgCol ~= nil then if (bgCol >= 1) and (bgCol <=44) and not variables.Collect.framed then local iHell = 0 iHell = iSchriftTab[bgCol] if txCol ~= 23 then -- Keine rote Schrift if (iHell == 1) then -- Hintergrund ist dunkel sColorDependBG = "White" changeColorByIndex(44, trans) else -- Hintergrund ist hell sColorDependBG = "Black" changeColorByIndex(43, trans) end else -- Wert ist negativ if bgCol == 23 then -- Rot auf Rot geht nicht sColorDependBG = "Black" changeColorByIndex(43, trans) else if (iHell == 1) then changeColorByIndex(22, trans) sColorDependBG = "LightRed" else sColorDependBG = "Red" changeColorByIndex(23, trans) end end end else -- Bei Transparentem Hintergrund wird der Invers-Schalter verwendet if txCol ~= 23 then if (variables.Collect.textInverse) then -- Hintergrund ist dunkel sColorDependBG = "White" changeColorByIndex(44, trans) else -- Hintergrund ist hell sColorDependBG = "Black" changeColorByIndex(43, trans) end else -- Wert ist negativ if (variables.Collect.textInverse) then -- Bei dunklem Hintergrund wird die kleine Schriftart unzulänglich angezeigt --> helles rot sColorDependBG = "LightRed" changeColorByIndex(22, trans) else sColorDependBG = "Red" changeColorByIndex(23, trans) end end end return sColorDependBG end end local function setLimits() rx.limits = {} for i=1, rx.count do rx.limits[i] = i <= 6 and 77 or i <= 9 and 100 or 0 end end local function setFlights() local time = system.getDateTime() local date = string.format("%d-%d-%d", time.year, time.mon, time.day) if (date ~= variables.Collect.flightDate) then variables.Collect.flightDate = date variables.Collect.flightsToday = 0 else variables.Sensors[variables.FightsIdx].valTotal = variables.Collect.flightsTotal variables.Sensors[variables.FightsIdx].valToday = variables.Collect.flightsToday end end local function partition(array1, array2, min, max) local pivot = array2[max]:lower() local i = min for j=min, max do if (array2[j]:lower() < pivot) then array1[i], array1[j] = array1[j], array1[i] array2[i], array2[j] = array2[j], array2[i] i = i + 1 end end array1[i], array1[max] = array1[max], array1[i] array2[i], array2[max] = array2[max], array2[i] return i end local function quicksort(array1, array2, min, max) if (min < max) then local p = partition(array1, array2, min, max) quicksort(array1, array2, min, p - 1) quicksort(array1, array2, p + 1, max) end end local function setJsnFiles() local i = 1 local index = 1 local current = 1 local files = {trans.empty} local folder = folder local extension = extensionJsonFile local chars = #extension local emulator = select(2, system.getDeviceType()) if (emulator == 0) then folder = "/"..folder:sub(1, -2) end for name, type in dir(folder) do if (type == "file" and name:sub(-chars):lower() == extension) then name = name:sub(1, -chars-1) if(string.find(name, "Timer") == 1) then index = index + 1 variables.BeepCmd.FileList[index] = name end end end end local function setJsnFilesLoadList(selectedfile) local i = 1 local index = 1 local current = 1 local files = {trans.empty} local folder = folder local extension = extensionJsonFile local chars = #extension local emulator = select(2, system.getDeviceType()) local completeFile = "" local iSnapShotFileIndex = 1 if (emulator == 0) then folder = "/"..folder:sub(1, -2) end for name, type in dir(folder) do if (type == "file" and name:sub(-chars):lower() == extension) then name = name:sub(1, -chars-1) if(string.find(name, "DApp") == 1) then -- Nicht alle json-Dateien sind ladbar für die Daten-Sicherung/Wiederherstellung) index = index + 1 files[index] = string.sub(name, 6, name:len()) -- Prefix noch entfernen end completeFile = "DApp_"..files[index]..extensionJsonFile if (completeFile == selectedfile) then current = index end end end variables.fileLoadList = files return current end local function setFiles() local i = 1 local index = 1 local current = 1 local files = {trans.empty} local folder = folder local extension = extensionFile local chars = #extension local emulator = select(2, system.getDeviceType()) local iSnapShotFileIndex = 1 if (emulator == 0) then folder = "/"..folder:sub(1, -2) end for name, type in dir(folder) do if (type == "file" and name:sub(-chars):lower() == extension) then name = name:sub(1, -chars-1) if(string.find(name, "SnapShot") == 1) then iSnapShotFileIndex = iSnapShotFileIndex + 1 variables.SnapShot.Files[iSnapShotFileIndex] = name else -- Die Snapshot-Dateien sind nicht ladbar für die Sicherung/Wiederherstellung) index = index + 1 files[index] = name end if (name == fileLoad) then current = index end end end -- [[ -- Alphabetisch sortieren local fileindices = {} for i=1, #files do fileindices[i] = i end quicksort(fileindices, files, 2, #files) --]] filesLoad = files -- [[ indexLoad = 1 for i=1, #files do if( files[i] == fileLoad) then indexLoad = i end end --]] --indexLoad = current end ------------------------------------------------------------------------------------------- -- Stabiler Insertion Sort Algorithmus, bis ca. 200 Elemente kein Unterschied zum Quicksort -- Texttabelle aufsteigend sortieren, 1. Element nicht berücksichtigen und keine -- Unterscheidung zwischen Groß- und Kleinschreibung. ------------------------------------------------------------------------------------------- local function stable_sort(t, compare) -- Standard-Vergleichsfunktion, falls keine übergeben wurde -- compare = compare or function(a, b) return a < b end compare = compare or function(a, b) return string.upper(a) < string.upper(b) end -- Groß- und Kleinschreibung ausgleichen -- for i = 2, #t do for i = 3, #t do -- das erste Element soll auslassen werden local key = t[i] local j = i - 1 -- Wichtig für Stabilität: Nur verschieben, wenn 'key' echt kleiner als t[j] ist -- while j > 0 and compare(key, t[j]) do while j > 1 and compare(key, t[j]) do -- das erste Element soll auslassen werden t[j + 1] = t[j] j = j - 1 end t[j + 1] = key end return t end local function setImages() local index = 1 local image = 1 local logo = 1 local battery = 1 local files = {trans.empty} local folder = folder local extension1 = extensionsImage[1] local extension2 = extensionsImage[2] local chars1 = #extension1 local chars2 = #extension2 local emulator = select(2, system.getDeviceType()) if (emulator == 0) then folder = "/"..folder:sub(1, -2) end for name, type in dir(folder) do if (type == "file") then if (name:sub(-chars1):lower() == extension1) then name = name:sub(1, -chars1-1) elseif (name:sub(-chars2):lower() == extension2) then name = name:sub(1, -chars2-1) else name = nil end if (name and name ~= files[index-1]) then index = index + 1 files[index] = name end end end -- Alphabetisch sortieren und weiterreichen filesImage = stable_sort(files) end local function loadImage(file) for _,extension in ipairs(extensionsImage) do local image = lcd.loadImage(folder..file..extension) if (image) then return image end end return false end local function getRSSI(value) local result if (value > 34) then result = 9 elseif (value > 27) then result = 8 elseif (value > 22) then result = 7 elseif (value > 18) then result = 6 elseif (value > 14) then result = 5 elseif (value > 10) then result = 4 elseif (value > 6) then result = 3 elseif (value > 3) then result = 2 elseif (value > 0) then result = 1 else result = 0 end return result end local function isSwitch(value) if (value) then local info = system.getSwitchInfo(value) return info and info.assigned end end local function drawBackground() if (background == nil) then background = loadImage("background") end if (background) then local width = 320 local height = 240 lcd.drawImage((width - math.min(width, background.width)) / 2, (height - math.min(height, background.height)) / 2, background) end end local function drawWarning(x, y) if (imageWarning == nil) then imageWarning = loadImage("warning6") end if (imageWarning) then local width = 50 local height = 44 lcd.drawImage(x + (width - math.min(width, imageWarning.width)) / 2, y + (height - math.min(height, imageWarning.height)) / 2, imageWarning) end end -- Datendefinitionen für die großen Zeichensätze local dD = { files = { -- Dateinamen der einzelen Zeichen ["0"] = "0"; ["1"] = "1"; ["2"] = "2"; ["3"] = "3"; ["4"] = "4"; ["5"] = "5"; ["6"] = "6"; ["7"] = "7"; ["8"] = "8"; ["9"] = "9"; ["."] = "point"; [":"] = "colon"; ["-"] = "minus"; }, widths = { -- Pixelbreiten für Size = 1; Pixelhöhe = 50 ["0"] = 39; ["1"] = 39; ["2"] = 39; ["3"] = 39; ["4"] = 39; ["5"] = 39; ["6"] = 39; ["7"] = 39; ["8"] = 39; ["9"] = 39; ["."] = 18; [":"] = 18; ["-"] = 24; }, factors = { -- Vergrößerungsfaktoren 0.8; 1; 1.2; 1.4; 1.6; } } local function getNumberHeight(size) local height = 0 height = 50 * dD.factors[size] return height end local function getNumberWidth(number, digits, size, text) local width = 0 digits = math.floor(digits + 0.5) -- Integer-Absicherung (typisches LUA 5.3 Problem) if text == nil then text = string.format("%."..digits.."f", number) else text = text:gsub(" ", "") -- Leerzeichen entfernen end local length = string.len(text) if digits > 0 then width = width + dD.widths["."] -- '.' und ':' haben die gleiche Breite length = length - 1 end if number < 0 then width = width + dD.widths["-"] length = length - 1 end width = (width + (length * 39)) * dD.factors[size] return width end -- d = Digit(0-9), Position xy, Größe g (1 - 5) local function drawDigit(x, y, digit, color, size, negativ) local right = false local file = string.format("Numbers/%s/%s/%s", size, color, dD.files[digit]) local width = dD.widths[digit] * dD.factors[size] local name = "image_"..file if (not dDimg[name]) then dDimg[name] = loadImage(file) end if (dDimg[name]) then lcd.drawImage(right and x - width or x, y, dDimg[name]) end return width end -- Zahlenausgabe mit beliebig vielen Stellen -- xy-Koordinaten, z=Zahl,komma stellen, links oder rechtsbündig, size=Größe(ordner) -- text = nil --> normale Darstellung -- text enthält eine Zeit mit einem Doppelpunkt positiv oder negativ local function drawNumber(x, y, number, digits, color, size, text) local right = false digits = math.floor(digits + 0.5) -- Integer-Absicherung (typisches LUA 5.3 Problem) if text == nil then text = string.format("%."..digits.."f", number) else text = text:gsub(" ", "") -- Leerzeichen entfernen end local length = string.len(text) local start = right and length or 1 local stop = right and 1 or length local step = right and -1 or 1 local digit, width local bNeg = false if (number < 0.0) then bNeg = true end for i=start, stop, step do digit = string.sub(text, i, i) width = drawDigit(x, y, digit, color, size, bNeg) x = x + width * step end end local function drawAlert(x, y) if (alert) then local text, font, width local step = 3000 local time = system.getTimeCounter() % (step * 2) if (time < step) then lcd.setColor(255, 0, 0) if (se.warning2 == nil) then se.warning2 = loadImage("warning2") end if (se.warning2) then lcd.drawImage(x, y, se.warning2) end setTextColorDependBG(44, 255, 43) font = FONT_BIG text = trans.throttle width = lcd.getTextWidth(font, text) lcd.drawText(x + 160 - width / 2, y + 76, text, font) text = trans.stick width = lcd.getTextWidth(font, text) lcd.drawText(x + 160 - width / 2, y + 96, text, font) text = trans.position width = lcd.getTextWidth(font, text) lcd.drawText(x + 160 - width / 2, y + 116, text, font) if (se.warning == nil) then se.warning = loadImage("warning") end if (se.warning) then lcd.drawImage(x + 160 - se.warning.width / 2, y + 50 - se.warning.height / 2, se.warning) end else if (se.warning1 == nil) then se.warning1 = loadImage("warning1") end if (se.warning1) then lcd.drawImage(x, y, se.warning1) end end end end local function drawBatteryAlert(x, y) if (batteryAlert and batteryAlert > 0) then local text, font, width if (se.akkuAlert == nil) then se.akkuAlert = loadImage("akkuAlert") end if (se.akkuAlert) then lcd.drawImage(x, y, se.akkuAlert) end setTextColorDependBG(44, 255, 43) font = FONT_MAXI text = trans.Ak width = lcd.getTextWidth(font, text) lcd.drawText(x + 160 - width / 2, y + 37, text, font) text = trans.is width = lcd.getTextWidth(font, text) lcd.drawText(x + 160 - width / 2, y + 67, text, font) setTextColorDependBG(43, 255, 0) font = FONT_NORMAL text = string.format("(%.2fV", variables.Vor.fValue) width = lcd.getTextWidth(font, text) lcd.drawText(x + 150 - width, y + 104, text, font) lcd.drawText(x + 154, y + 103, "<", FONT_BIG) font = FONT_NORMAL text = string.format("%.1fV)", se.vorflugvolt / 10) width = lcd.getTextWidth(font, text) lcd.drawText(x + 210 - width, y + 104, text, font) end end -- Zeichnet den eigentlichen farbigen Balken (Grün/Gelb/Rot-Bereiche). local function drawBar(bx, by, mw, mh, vl, wl, al, bGrowing, tr, iR, iY, iG) if bGrowing then -------------------------------------------------------------- -- GROWING-MODUS: Alarm wird bei steigenden Werten ausgelöst -- (z.B. Stromverbrauch steigt über die Schwelle) -------------------------------------------------------------- if (vl >= al) then -- Fall 1: Wert liegt im ALARM-Bereich (oberhalb Alarm-Schwelle) -- Alle drei Farbbereiche werden gezeichnet. -- Sicherheitscheck: Wert darf die maximale Höhe nicht überschreiten if (mh < vl) then vl = mh end -- Roter Bereich: von Oberkante des Balkens bis Alarm-Schwelle changeColorByIndex(iR, tr) lcd.drawFilledRectangle(bx, by + mh - vl, mw, vl - al, tr) -- Gelber Bereich: von Alarm-Schwelle bis Warning-Schwelle changeColorByIndex(iY, tr) lcd.drawFilledRectangle(bx, by + mh - al, mw, al - wl, tr) -- Grüner Bereich: von Warning-Schwelle bis Unterkante changeColorByIndex(iG, tr) lcd.drawFilledRectangle(bx, by + mh - wl, mw, wl, tr) elseif (vl >= wl) then -- Fall 2: Wert liegt im WARNING-Bereich (zwischen Warning und Alarm) -- Nur gelber und grüner Bereich werden gezeichnet. -- Gelber Bereich: von Oberkante bis Warning-Schwelle changeColorByIndex(iY, tr) lcd.drawFilledRectangle(bx, by + mh - vl, mw, vl - wl, tr) -- Grüner Bereich: von Warning-Schwelle bis Unterkante changeColorByIndex(iG, tr) lcd.drawFilledRectangle(bx, by + mh - wl, mw, wl, tr) else -- Fall 3: Wert liegt im NORMAL-Bereich (unterhalb Warning) -- Nur grüner Bereich wird gezeichnet. changeColorByIndex(iG, tr) lcd.drawFilledRectangle(bx, by + mh - vl, mw, vl, tr) end else -------------------------------------------------------------- -- SHRINKING-MODUS: Alarm wird bei fallenden Werten ausgelöst -- (z.B. Akku-/Tankfüllstand sinkt unter die Schwelle) -- -- Hier ist die Farblogik invertiert: -- Niedriger Wert = Gefahr = Rot -- Hoher Wert = OK = Grün -------------------------------------------------------------- if (vl <= al) then -- Fall 1: Wert liegt im ALARM-Bereich (unterhalb Alarm-Schwelle) -- Gesamter sichtbarer Balken ist rot. changeColorByIndex(iR, tr) lcd.drawFilledRectangle(bx, by + mh - vl, mw, vl, tr) elseif (vl <= wl) then -- Fall 2: Wert liegt im WARNING-Bereich (zwischen Alarm und Warning) -- Oberer Teil gelb, unterer Teil rot. -- Gelber Bereich: von Oberkante bis Alarm-Schwelle changeColorByIndex(iY, tr) lcd.drawFilledRectangle(bx, by + mh - vl, mw, vl - al, tr) -- Roter Bereich: von Alarm-Schwelle bis Unterkante changeColorByIndex(iR, tr) lcd.drawFilledRectangle(bx, by + mh - al, mw, al, tr) else -- Fall 3: Wert liegt im NORMAL-Bereich (oberhalb Warning) -- Alle drei Farbbereiche werden gezeichnet. -- Grüner Bereich: von Oberkante bis Warning-Schwelle changeColorByIndex(iG, tr) lcd.drawFilledRectangle(bx, by + mh - vl, mw, vl - wl, tr) -- Gelber Bereich: von Warning-Schwelle bis Alarm-Schwelle changeColorByIndex(iY, tr) lcd.drawFilledRectangle(bx, by + mh - wl, mw, wl - al, tr) -- Roter Bereich: von Alarm-Schwelle bis Unterkante changeColorByIndex(iR, tr) lcd.drawFilledRectangle(bx, by + mh - al, mw, al, tr) end end end -- Füllt den Bereich OBERHALB des aktuellen Balkenwerts mit der -- konfigurierten Hintergrundfarbe. Dadurch wird der "leere" Teil -- des Balkens visuell sichtbar (z.B. grau hinterlegt). local function drawBackgrnd(bx, by, mw, mh, vl, bgColor, tr) if (bgColor > 0) then changeColorByIndex(bgColor, tr) lcd.drawFilledRectangle(bx, by, mw, mh - vl, tr) end end -- Verarbeitet Warning-/Alarm-Meldungen im GROWING-Modus. -- Im Growing-Modus werden Schwellwerte von UNTEN nach OBEN überschritten, -- d.h. Warning/Alarm wird ausgelöst wenn vl >= wl bzw. vl >= al. local function handleAlertsGrowing(vl, wl, al, idx, sensorName, warnVal, alarmVal, warnSound, alarmSound, bAgain, bAnsage, sUnit) -- Kurzreferenz auf die Konfigurationstabelle local at = SpecTiles.AkkuTank -- === WARNING-Prüfung === -- Auslösung: Wert >= Warning-Schwelle UND Meldung wurde noch nicht gesendet if (vl >= wl) and (not at["bWarningSend"..idx]) then -- Flag setzen: Meldung wurde gesendet (verhindert Mehrfachauslösung) at["bWarningSend"..idx] = true -- Meldung auf dem Display anzeigen (3 = Typ der MessageBox) system.messageBox("Warning "..idx..": "..sensorName.." > "..warnVal.." "..sUnit, 3) if at["iLockNewPlay"..idx] == 0 then -- Einträge sind freigegeben at["iLockNewPlay"..idx] = system.getTime() + 1 -- für eine Sekunde gesperrt --print("Gesperrt von handleAlertsGrowing(Warning) um " .. system.getTime() .. " bis " .. at["iLockNewPlay"..idx]) for i = 1, bAgain and 3 or 1 do if (warnSound ~= "...") then system.playFile(warnSound, AUDIO_QUEUE) end if bAnsage then system.playNumber(warnVal, 0, sUnit) end end end end -- === ALARM-Prüfung === -- Auslösung: Wert >= Alarm-Schwelle UND Meldung wurde noch nicht gesendet if (vl >= al) and (not at["bAlarmSend"..idx]) then at["bAlarmSend"..idx] = true system.messageBox("Alarm "..idx..": "..sensorName.." > "..alarmVal.." "..sUnit, 3) -- Identisches Verhalten wie bei Warning (siehe oben). if at["iLockNewPlay"..idx] == 0 then -- Einträge sind freigegeben at["iLockNewPlay"..idx] = system.getTime() + 1 -- für eine Sekunde gesperrt --print("Gesperrt von handleAlertsGrowing(Alarm) um " .. system.getTime() .. " bis " .. at["iLockNewPlay"..idx]) for i = 1, bAgain and 3 or 1 do if (alarmSound ~= "...") then system.playFile(alarmSound, AUDIO_QUEUE) end if bAnsage then system.playNumber(alarmVal, 0, sUnit) end end end end -- === SPERREN ZURÜCKSETZEN === -- Wenn der Wert wieder unter die Schwelle fällt, wird das Flag -- zurückgesetzt, damit die Meldung beim nächsten Überschreiten -- erneut ausgelöst werden kann. if (vl < al) and at["bAlarmSend"..idx] then at["bAlarmSend"..idx] = false end if (vl < wl) and at["bWarningSend"..idx] then at["bWarningSend"..idx] = false end end -- Verarbeitet Warning-/Alarm-Meldungen im SHRINKING-Modus. -- Im Shrinking-Modus werden Schwellwerte von OBEN nach UNTEN unterschritten, -- d.h. Warning/Alarm wird ausgelöst wenn vl <= wl bzw. vl <= al. local function handleAlertsShrinking(vl, wl, al, idx, sensorName, warnVal, alarmVal, warnSound, alarmSound, bAgain, bAnsage, sUnit) local at = SpecTiles.AkkuTank -- === WARNING-Prüfung === if (vl <= wl) and (not at["bWarningSend"..idx]) then at["bWarningSend"..idx] = true system.messageBox("Warning"..idx..": "..sensorName.." < "..warnVal.." "..sUnit, 3) -- Audio ggf. 3× abspielen (gesteuert durch bAgain) -- und bAnsage (= bAnsageRestmenge) if at["iLockNewPlay"..idx] == 0 then -- Einträge sind freigegeben at["iLockNewPlay"..idx] = system.getTime() + 1 -- nun für eine Sekunde gesperrt --print("Gesperrt von handleAlertsShrinking(Warning) um " .. system.getTime() .. " bis " .. at["iLockNewPlay"..idx]) for i = 1, bAgain and 3 or 1 do if (warnSound ~= "...") then system.playFile(warnSound, AUDIO_QUEUE) end if bAnsage then system.playNumber(warnVal, 0, sUnit) end end end end -- === ALARM-Prüfung === if (vl <= al) and (not at["bAlarmSend"..idx]) then at["bAlarmSend"..idx] = true system.messageBox("Alarm"..idx..": "..sensorName.." < "..alarmVal.." "..sUnit, 3) -- Identisches Verhalten wie bei Warning (siehe oben). if at["iLockNewPlay"..idx] == 0 then -- Einträge sind freigegeben at["iLockNewPlay"..idx] = system.getTime() + 1 -- nun für eine Sekunde gesperrt --print("Gesperrt von handleAlertsShrinking(Alarm) um " .. system.getTime() .. " bis " .. at["iLockNewPlay"..idx]) for i = 1, bAgain and 3 or 1 do if (alarmSound ~= "...") then system.playFile(alarmSound, AUDIO_QUEUE) end if bAnsage then system.playNumber(alarmVal, 0, sUnit) end end end end -- === SPERREN ZURÜCKSETZEN === -- Im Shrinking-Modus wird die Sperre aufgehoben, wenn der Wert -- wieder ÜBER die Schwelle steigt (Zustand verbessert sich). if (vl > wl) and at["bWarningSend"..idx] then at["bWarningSend"..idx] = false end if (vl > al) and at["bAlarmSend"..idx] then at["bAlarmSend"..idx] = false end end -- Zeichnet eine Skala mit 10 Markierungsstrichen am linken und rechten -- Rand des Balkens. Bei 50% und 100% werden die Striche doppelt so lang. local function drawScale(bx, by, mw, mh, lineLen) -- Farbe: Weiß bei inversem Hintergrund, sonst Schwarz if variables.Collect.textInverse then changeColorByIndex(44, 255) -- 44 = Weiß, volle Deckkraft else changeColorByIndex(43, 255) -- 43 = Schwarz, volle Deckkraft end for i = 1, 10 do -- Y-Position für diesen Skalenstrich berechnen -- Der Strich liegt bei i*10% der Gesamthöhe, gemessen von unten local yPos = by + mh - math.floor(i * mh / 10) -- Normaler Strich: links und rechts am Balkenrand lcd.drawFilledRectangle(bx, yPos, lineLen, 2) lcd.drawFilledRectangle(bx + mw - lineLen, yPos, lineLen, 2) -- Bei 50% und 100%: doppelt langer Strich für bessere Ablesbarkeit if (i == 5) or (i == 10) then lcd.drawFilledRectangle(bx, yPos, 2 * lineLen, 2) lcd.drawFilledRectangle(bx + mw - 2 * lineLen, yPos, 2 * lineLen, 2) end end end -- Ermittelt die größtmögliche Schriftart, mit der 'text' noch in die -- verfügbare Breite 'maxW' passt. local function fitFont(text, maxW) local font = FONT_MAXI local h = lcd.getTextHeight(font) local w = lcd.getTextWidth(font, text) if (w > maxW) then -- FONT_MAXI passt nicht → FONT_BOLD versuchen font = FONT_BOLD h = lcd.getTextHeight(font) w = lcd.getTextWidth(font, text) if (w > maxW) then -- FONT_BOLD passt auch nicht → FONT_MINI als Fallback font = FONT_MINI h = lcd.getTextHeight(font) w = lcd.getTextWidth(font, text) end end return font, w, h end -- Zeichnet die Textbeschriftungen innerhalb/unterhalb eines Balkens. -- Es werden vier Textelemente dargestellt: local function drawBarTexts(bx, by, mw, mh, val, unitText, repText, repUnit, isDual, bgCol) -- Textfarbe setzen (Schwarz oder Weiß je nach Hintergrund) setTextColorDependBG(43, 255, bgCol) -- --- Zeile 1: Sensorwert (z.B. "85") --- local text = string.format("%d", val) local font, width, heightMax = fitFont(text, mw) -- Position: horizontal zentriert, vertikal bei 35% der Balkenhöhe lcd.drawText(bx + (mw - width) / 2, by + mh * 0.35 - heightMax / 2, text, font) -- --- Zeile 2: Einheit des Istwertes (z.B. "%" oder "mAh") --- font = FONT_BOLD local height = lcd.getTextHeight(font) text = unitText width = lcd.getTextWidth(font, text) -- Fallback auf kleinere Schrift wenn Text zu breit if (width > mw) then font = FONT_MINI height = lcd.getTextHeight(font) width = lcd.getTextWidth(font, text) end -- Position: direkt unter dem Sensorwert (35% + halbe Höhe) lcd.drawText(bx + (mw - width) / 2, by + mh * 0.35 + height / 2, text, font) -- --- Zeile 3: Physikalischer Maximalwert (z.B. "5000") --- font = FONT_NORMAL height = lcd.getTextHeight(font) text = string.format("%s", repText) width = lcd.getTextWidth(font, text) if (width > mw) then font = FONT_MINI width = lcd.getTextWidth(font, text) end -- Position: 2 Zeilen vom unteren Rand lcd.drawText(bx + (mw - width) / 2, by + mh - 2 * height, text, font) -- --- Zeile 4: Physikalische Einheit (z.B. "mAh" oder "ml") --- -- Bei Doppeldarstellung: kleinere Schrift wegen Platzmangel if isDual then font = FONT_MINI height = lcd.getTextHeight(font) end text = string.format("%s", repUnit) width = lcd.getTextWidth(font, text) -- Position: 1 Zeile vom unteren Rand, mit 3px Abstand lcd.drawText(bx + (mw - width) / 2, by + mh - height - 3, text, font) end -- Liest einen Sensorwert aus, wobei zwischen zwei Sensor-Typen -- unterschieden wird. local function readSensor(sensorType, sensorIdx, sensorId, sensorValNo) if (sensorType == 2) then -- Interner Sensor (Sender-Telemetrie) if variables.Sensors[sensorIdx] ~= nil then return variables.Sensors[sensorIdx].value else return 0.0 end else -- Externer Sensor (Receiver-Telemetrie) -- sensorValNo ist 1-basiert in der Konfiguration, -- die API erwartet aber 0-basiert → daher -1 local pt = system.getSensorValueByID(sensorId, sensorValNo - 1) if (pt ~= nil) then return pt.value end end return nil end -- Bereitet einen rohen Sensorwert für die Balkenanzeige auf: local function processValue(val, korrFaktor, bConvert, iMaxBarVal, capacity, maxH) -- Schritt 1: Korrekturfaktor anwenden val = val * tonumber(korrFaktor) local displayVal = val if bConvert then -- Schritt 2a: Grow-to-Shrink-Konvertierung -- Aus einem wachsenden Wert (z.B. 0→5000 mAh verbraucht) -- wird ein schrumpfender Prozentwert (z.B. 100%→0% Rest) val = iMaxBarVal - math.floor(iMaxBarVal * val / capacity) -- Wert darf nicht negativ werden (Überverbrauch) if (val < 0.0) then val = 0.0 end displayVal = val -- Skalierung auf Pixel-Höhe, bezogen auf MaxBarValue return val, math.floor(maxH * val / iMaxBarVal), displayVal else -- Schritt 2b: Direkter Modus (keine Konvertierung) -- Wert nach oben begrenzen (darf Kapazität nicht überschreiten) if (val > capacity) then val = capacity end displayVal = val -- Skalierung auf Pixel-Höhe, bezogen auf Kapazität return val, math.floor(maxH * val / capacity), displayVal end end -- Steuert die Sprachausgabe des aktuellen Sensorwertes. -- Die Ansage wird durch einen Schalter (Switch) ausgelöst und durch -- ein Semaphor-Flag geschützt, damit der Wert nicht mehrfach -- gleichzeitig angesagt wird. local function handlePlayback(command, bSema, semaKey, val, bConvert, unit) local at = SpecTiles.AkkuTank local iActTime = system.getTime() -- Kommando liegt an if command then -- Zeitstufe starten if (at[semaKey] == 0) then at[bSema] = false -- Neue Ausgabe freigegeben at[semaKey] = iActTime + 3 -- 3 Sekunden Verzögerungszeit für anstehendes Kommando -- Prüfen, ob die Zeitstufe abgelaufen ist elseif (iActTime >= at[semaKey]) then command = false -- Zeitstufe abgelaufen Kommando löschen at[semaKey] = 0 end -- Ansage ausführen: Kommando steht an UND Semaphor nicht gesetzt UND kein anderes Audio läuft if not system.isPlayback() then if not at[bSema] then at[bSema] = true -- Sperre: Keine neue Auagabe if bConvert then -- Bei Grow-to-Shrink: Wert als Prozentzahl ansagen system.playNumber(val, 0, "%") else -- Sonst: Wert mit physikalischer Einheit ansagen system.playNumber(val, 0, unit) end end end end -- Rückgabe des aktuellen Kommandos zum Speichern return command end -- Ablauf: -- 1. Initialisierung (Farben, Kachelgröße, Division-durch-Null-Schutz) -- 2. Hintergrundbild laden/aktualisieren -- 3. Layout berechnen (Einzel- vs. Doppeldarstellung, mit/ohne Bild) -- 4. Warn-/Alarmschwellen berechnen -- 5. Sensorwerte lesen -- 6. Für jeden Sensor (1 und optional 2): -- a. Wert aufbereiten (Korrekturfaktor, Konvertierung, Skalierung) -- b. Sprachausgabe steuern -- c. Balken zeichnen -- d. Hintergrund zeichnen -- e. Meldungen verarbeiten -- f. Skala zeichnen -- g. Texte zeichnen function ka.drawBarChart(x, y) local bAnsageRestmenge = SpecTiles.AkkuTank.bAnsageRestmenge -- 1. INITIALISIERUNG local at = SpecTiles.AkkuTank -- Farbindizes für die Balkenanzeige -- Bei inversem Hintergrund werden dunklere Farbtöne verwendet local iRed, iYellow, iGreen = 23, 26, 29 if variables.Collect.textInverse then iRed, iYellow, iGreen = 24, 27, 30 end -- Kachelgröße: Breite ist fest 53px, Höhe ist konfigurierbar local iKachelWidth = 53 local iKachelHeight = at.iTilesHeigtht -- Schutz gegen Division durch Null bei der Skalierung -- (Kapazität wird als Divisor verwendet) if (at.iCapacity1 == 0) then at.iCapacity1 = 1 end if (at.iCapacity2 == 0) then at.iCapacity2 = 1 end -- Standardfarbe setzen (Schwarz für Rahmen etc.) --changeColor(colors.color43) changeColorByIndex(43,255) -- 2. HINTERGRUNDBILD LADEN / AKTUALISIEREN if (at.imgPicFile == nil) then -- Noch kein Bild geladen → versuchen zu laden if (at.sPicFileName ~= "EmptyPic") and (at.sPicFileName ~= "leer") then at.imgPicFile = loadImage(at.sPicFileName) end else -- Bild bereits geladen → prüfen ob Änderung vorliegt if (at.bPicFileChanged == true) then at.imgPicFile = loadImage(at.sPicFileName) at.bPicFileChanged = false -- Änderung verarbeitet end end -- 3. LAYOUT BERECHNEN local iOffsetX, iOffsetY, iMaxHeight, iMaxWidth, iLineLength local iOffsetX2, iOffsetY2, iMaxHeight2, iMaxWidth2 -- Bestimmen ob Einzel- oder Doppeldarstellung local isDual = (at.iAccOfStorage == 2) -- Prüfen ob ein Hintergrundbild vorhanden und gültig ist local hasImage = (at.imgPicFile ~= nil) and (at.imgPicFile ~= false) if not isDual then -- ---- EINZELDARSTELLUNG ---- if hasImage then -- Mit Hintergrundbild: Balken wird etwas eingerückt lcd.drawImage(x + 1, y + 0, at.imgPicFile) iOffsetX = 3 iOffsetY = 6 iMaxHeight = iKachelHeight - 8 -- 6px oben + 2px unten Rand iMaxWidth = iKachelWidth - 6 -- 3px links + 3px rechts iLineLength = 3 else -- Ohne Bild: Rahmen zeichnen, Balken füllt fast die ganze Kachel iOffsetX = 1 iOffsetY = 1 iMaxHeight = iKachelHeight - 2 -- 1px Rand oben + unten iMaxWidth = iKachelWidth -- Volle Breite iLineLength = 4 lcd.drawRectangle(x, y, iKachelWidth, iKachelHeight) end else -- ---- DOPPELDARSTELLUNG ---- -- Zwei Balken nebeneinander, jeder halb so breit if hasImage then lcd.drawImage(x + 1, y + 0, at.imgPicFile) iOffsetX = 3 iOffsetY = 6 iMaxHeight = iKachelHeight - 8 iMaxWidth = (iKachelWidth - 8) / 2 -- Halbe Breite minus Ränder iLineLength = 3 -- Sensor 2: rechts neben Sensor 1 positioniert iOffsetX2 = 6 + iMaxWidth -- 3px + Breite Balken1 + 3px Abstand iOffsetY2 = iOffsetY iMaxHeight2 = iMaxHeight iMaxWidth2 = iMaxWidth else iOffsetX = 1 iOffsetY = 1 iMaxHeight = iKachelHeight - 2 iMaxWidth = (iKachelWidth - 5) / 2 -- Halbe Breite minus Zwischenraum iLineLength = 3 -- Rahmen für linken Balken lcd.drawRectangle(x, y, iKachelWidth / 2, iKachelHeight) -- Sensor 2: rechte Hälfte iOffsetX2 = 3 + iMaxWidth iOffsetY2 = 1 iMaxHeight2 = iKachelHeight - 2 iMaxWidth2 = iMaxWidth -- Rahmen für rechten Balken lcd.drawRectangle(x + iKachelWidth / 2, y, iKachelWidth / 2, iKachelHeight) end end -- 4. WARN-/ALARMSCHWELLEN BERECHNEN local iWarningLevel1 = math.floor(iMaxHeight * at.iWarningValue1 / at.iCapacity1) local iAlarmLevel1 = math.floor(iMaxHeight * at.iAlarmValue1 / at.iCapacity1) -- 5. SENSORWERTE LESEN -- Sensor-Wert-Nr. absichern (muss mindestens 2 sein) if (at.iSensorValueNo1 < 2) then at.iSensorValueNo1 = 2 end -- Sensorwert 1 auslesen local value = readSensor(at.iSensorType1, at.iSensorValueIdx1, at.iSensorId1, at.iSensorValueNo1) -- Sensorwert 2 auslesen (nur bei Doppeldarstellung) local value2 = nil local iWarningLevel2, iAlarmLevel2, iValueLevel2 if isDual then -- Schwellen für Sensor 2 berechnen iWarningLevel2 = math.floor(iMaxHeight * at.iWarningValue2 / at.iCapacity2) iAlarmLevel2 = math.floor(iMaxHeight * at.iAlarmValue2 / at.iCapacity2) if (at.iSensorValueNo2 < 2) then at.iSensorValueNo2 = 2 end value2 = readSensor(at.iSensorType2, at.iSensorValueIdx2, at.iSensorId2, at.iSensorValueNo2) end -- 6a. SENSOR 1 VERARBEITEN UND DARSTELLEN if (value ~= nil) then -- Wert aufbereiten: Korrekturfaktor, Konvertierung, Skalierung local iValueLevel1 value, iValueLevel1, at.fValueAct1 = processValue( value, -- Roher Sensorwert at.sKorrekturfaktor1, -- Kalibrierungsfaktor at.bConvertGrowToShrk1, -- Grow-to-Shrink? at.iMaxBarValue1, -- Max-Wert für Balken (bei Konvertierung) at.iCapacity1, -- Sensor-Kapazität iMaxHeight -- Pixel-Höhe des Balkens ) local unitText1 = at.bConvertGrowToShrk1 and "%" or at.sSensorUnit1 -- Sprachausgabe des Sensorwertes (bei Schalterdruck) at.bCommandPlay1 = handlePlayback(at.bCommandPlay1, "bSemaPlay1", "iLockNewPlay1", value, at.bConvertGrowToShrk1, unitText1) -- Basis-Koordinaten für Sensor 1 vorberechnen local bx = x + iOffsetX local by = y + iOffsetY -- (a) Farbigen Balken zeichnen drawBar(bx, by, iMaxWidth, iMaxHeight, iValueLevel1, iWarningLevel1, iAlarmLevel1, at.bGrowing1, at.iTransparenz, iRed, iYellow, iGreen) -- (b) Hintergrund für den leeren Bereich oberhalb des Balkens drawBackgrnd(bx, by, iMaxWidth, iMaxHeight, iValueLevel1, at.iBgColor, at.iTransparenz) -- (c) Warning/Alarm-Meldungen verarbeiten if variables.bLimitWatchReleased then if at.bGrowing1 then -- Growing-Modus: Alarm bei steigenden Werten handleAlertsGrowing(iValueLevel1, iWarningLevel1, iAlarmLevel1, "1", at.sSensorValueName1, at.iWarningValue1, at.iAlarmValue1, at.sWarningSound1, at.sAlarmSound1, se.again1, bAnsageRestmenge, unitText1) else -- Shrinking-Modus: Alarm bei fallenden Werten handleAlertsShrinking(iValueLevel1, iWarningLevel1, iAlarmLevel1, "1", at.sSensorValueName1, at.iWarningValue1, at.iAlarmValue1, at.sWarningSound1, at.sAlarmSound1, se.again1, bAnsageRestmenge, unitText1) end end if (at.iLockNewPlay1 > 0) and (at.iLockNewPlay1 < system.getTime()) then -- Wartezeit abgelaufen, Lock wieder freigeben at.iLockNewPlay1 = 0 end if (at.iLockNewPlay2 > 0) and (at.iLockNewPlay2 < system.getTime()) then at.iLockNewPlay2 = 0 end -- (d) Skala zeichnen (wenn aktiviert) if (at.bShowScale == true) then drawScale(bx, by, iMaxWidth, iMaxHeight, iLineLength) end -- (e) Texte zeichnen (Wert, Einheit, Beschriftungen) drawBarTexts(bx, by, iMaxWidth, iMaxHeight, value, unitText1, at.sRepresentation1, at.sRepresentUnit1, isDual, at.iBgColor) end -- 6b. SENSOR 2 VERARBEITEN UND DARSTELLEN (nur Doppeldarstellung) if (value2 ~= nil) then value2, iValueLevel2, at.fValueAct2 = processValue( value2, at.sKorrekturfaktor2, at.bConvertGrowToShrk2, at.iMaxBarValue2, at.iCapacity2, iMaxHeight2 ) local unitText2 = at.bConvertGrowToShrk2 and "%" or at.sSensorUnit2 -- Sprachausgabe Sensor 2 at.bCommandPlay2 = handlePlayback(at.bCommandPlay2, "bSemaPlay2", "iLockNewPlay2", value2, at.bConvertGrowToShrk2, unitText2) -- Basis-Koordinaten für Sensor 2 local bx2 = x + iOffsetX2 local by2 = y + iOffsetY2 -- (a) Balken zeichnen drawBar(bx2, by2, iMaxWidth2, iMaxHeight2, iValueLevel2, iWarningLevel2, iAlarmLevel2, at.bGrowing2, at.iTransparenz, iRed, iYellow, iGreen) -- (b) Hintergrund drawBackgrnd(bx2, by2, iMaxWidth2, iMaxHeight2, iValueLevel2, at.iBgColor, at.iTransparenz) -- (c) Warning/Alarm-Meldungen verarbeiten if variables.bLimitWatchReleased then if at.bGrowing2 then -- Growing-Modus: Alarm bei steigenden Werten handleAlertsGrowing(iValueLevel2, iWarningLevel2, iAlarmLevel2, "2", at.sSensorValueName2, at.iWarningValue2, at.iAlarmValue2, at.sWarningSound2, at.sAlarmSound2, se.again2, bAnsageRestmenge, unitText2) else -- Shrinking-Modus: Alarm bei fallenden Werten handleAlertsShrinking(iValueLevel2, iWarningLevel2, iAlarmLevel2, "2", at.sSensorValueName2, at.iWarningValue2, at.iAlarmValue2, at.sWarningSound2, at.sAlarmSound2, se.again2, bAnsageRestmenge, unitText2) end end -- (d) Skala if (at.bShowScale == true) then drawScale(bx2, by2, iMaxWidth2, iMaxHeight2, iLineLength) end -- (e) Texte drawBarTexts(bx2, by2, iMaxWidth2, iMaxHeight2, value2, unitText2, at.sRepresentation2, at.sRepresentUnit2, isDual, at.iBgColor) end end ------------------------------------------- -- Daten der Empfänger darstellen -- REX -- ------------------------------------------- function ka.drawRx(x, y, label, mini, antenna1, antenna2, percent, voltage, SemaQ, SemaA1, SemaA2) if (mini) then local font, text, width font = FONT_MINI if (voltage < 3.8) then changeColorByIndex(variables.Rex.Selected.bgColorOFF,255) -- rot drawKaBackground(x + 2, y + 0, 128, 22) changeColorByIndex(variables.Rex.Selected.txColorOFF,255) -- weiß else changeColorByIndex(variables.Rex.Selected.bgColorON,255) -- grün drawKaBackground(x + 2, y + 0, 128, 22) changeColorByIndex(variables.Rex.Selected.txColorON,255) -- schwarz end lcd.drawText(x + 5, y + 9, "("..label..")", font) lcd.drawText(x + 4, y + 0, trans.receiver..":", font) lcd.drawText(x + 57, y + 4, "V", FONT_NORMAL) lcd.drawText(x + 23, y + 2, string.format("%.2f", voltage), FONT_BIG) -- Qualität if SemaQ then -- Abgelaufene Zeitstufe mit Farbumschlag anzeigen changeColorByIndex(variables.Rex.Selected.txColorONerror, 255) text = string.format("Q: %03.0f / %03.0f", percent, variables.Rex.Selected.Qlimit) width = lcd.getTextWidth(font, text) lcd.drawText(x + 128 - width, y + 0, text, font) changeColorByIndex(variables.Rex.Selected.txColorON,255) else -- Text in normaler Farbe text = string.format("Q: %03.0f / %03.0f", percent, variables.Rex.Selected.Qlimit) width = lcd.getTextWidth(font, text) -- lcd.drawText(x + 126 - width, y + 0, text, font) lcd.drawText(x + 128 - width, y + 0, text, font) end -- Antennen A1 und A2 text = string.format("A1:%01.0f/%01.0f", getRSSI(antenna1), variables.Rex.Selected.A1limit) local text2 if SemaA2 then changeColorByIndex(variables.Rex.Selected.txColorONerror, 255) text2 = string.format("%s A2:%01.0f/%01.0f", text, getRSSI(antenna2), variables.Rex.Selected.A2limit) width = lcd.getTextWidth(font, text2) lcd.drawText(x + 129 - width, y + 10, text, FONT_MINI) changeColorByIndex(variables.Rex.Selected.txColorON, 255) else -- Text in normaler Farbe text2 = string.format("%s A2:%01.0f/%01.0f", text, getRSSI(antenna2), variables.Rex.Selected.A2limit) width = lcd.getTextWidth(font, text2) lcd.drawText(x + 129 - width, y + 10, text2, FONT_MINI) end else --Big... local font, text, width font = FONT_MINI if (voltage < 3.8) then changeColorByIndex(variables.Rex.Selected.bgColorOFF,255) -- rot drawKaBackground(x + 2, y + 0, 128, 31) changeColorByIndex(variables.Rex.Selected.txColorOFF,255) -- weiß else changeColorByIndex(variables.Rex.Selected.bgColorON,255) -- grün drawKaBackground(x + 2, y + 0, 128, 31) changeColorByIndex(variables.Rex.Selected.txColorON,255) -- schwarz end lcd.drawText(x + 6, y + 0, "R", FONT_MINI) lcd.drawText(x + 6, y + 9, "X", FONT_MINI) lcd.drawText(x + 4, y + 18, "("..label..")", font) --IG lcd.drawText(x + 78, y + 11, "V", FONT_BIG) lcd.drawText(x + 17, y - 3, string.format("%.2f", voltage), FONT_MAXI) -- Qualität if SemaQ then -- Abgelaufene Zeitstufe mit Farbumschlag anzeigen changeColorByIndex(variables.Rex.Selected.txColorONerror, 255) text = string.format("Q: %03.0f / %03.0f", percent, variables.Rex.Selected.Qlimit) width = lcd.getTextWidth(font, text) lcd.drawText(x + 128 - width, y + 0, text, FONT_MINI) changeColorByIndex(variables.Rex.Selected.txColorON,255) else -- Text in normaler Farbe text = string.format("Q: %03.0f / %03.0f", percent, variables.Rex.Selected.Qlimit) width = lcd.getTextWidth(font, text) lcd.drawText(x + 129 - width, y + 0, text, FONT_MINI) end -- Antennen A1 und A2 if SemaA1 then -- Abgelaufene Zeitstufe mit Farbumschlag anzeigen changeColorByIndex(variables.Rex.Selected.txColorONerror, 255) text = string.format("A1: %01.0f / %01.0f", getRSSI(antenna1), variables.Rex.Selected.A1limit) width = lcd.getTextWidth(font, text) lcd.drawText(x + 128 - width, y + 10, text, FONT_MINI) changeColorByIndex(variables.Rex.Selected.txColorON,255) else -- Text in normaler Farbe text = string.format("A1: %01.0f / %01.0f", getRSSI(antenna1), variables.Rex.Selected.A1limit) width = lcd.getTextWidth(font, text) lcd.drawText(x + 128 - width, y + 10, text, FONT_MINI) end if SemaA2 then -- Abgelaufene Zeitstufe mit Farbumschlag anzeigen changeColorByIndex(variables.Rex.Selected.txColorONerror, 255) text = string.format("A2: %01.0f / %01.0f", getRSSI(antenna2), variables.Rex.Selected.A2limit) width = lcd.getTextWidth(font, text) lcd.drawText(x + 128 - width, y + 19, text, FONT_MINI) changeColorByIndex(variables.Rex.Selected.txColorON,255) else -- Text in normaler Farbe text = string.format("A2: %01.0f / %01.0f", getRSSI(antenna2), variables.Rex.Selected.A2limit) width = lcd.getTextWidth(font, text) lcd.drawText(x + 128 - width, y + 19, text, FONT_MINI) end end end function ka.drawRxMaxi1(x, y) -- Primärer Empfänger große Darstellung local disp = variables.Rex.Display return ka.drawRx(x, y, "P", false, rx.values[1], rx.values[2], rx.values[7], rx.values[10], disp.SemaphoreQ1, disp.SemaphoreA11, disp.SemaphoreA21) end function ka.drawRxMini1(x, y) -- Primärer Empfänger kleine Darstellung local disp = variables.Rex.Display return ka.drawRx(x, y, "P", true, rx.values[1], rx.values[2], rx.values[7], rx.values[10], disp.SemaphoreQ1, disp.SemaphoreA11, disp.SemaphoreA21) end function ka.drawRxMaxi2(x, y) -- Empfängerspannung 2 local disp = variables.Rex.Display return ka.drawRx(x, y, "S", false, rx.values[3], rx.values[4], rx.values[8], rx.values[11], disp.SemaphoreQ2, disp.SemaphoreA12, disp.SemaphoreA22) end function ka.drawRxMini2(x, y) -- Empfängerspannung 2 local disp = variables.Rex.Display return ka.drawRx(x, y, "S", true, rx.values[3], rx.values[4], rx.values[8], rx.values[11], disp.SemaphoreQ2, disp.SemaphoreA12, disp.SemaphoreA22) end function ka.drawRxMaxi3(x, y) -- Empfängerspannung 3 local disp = variables.Rex.Display return ka.drawRx(x, y, "B", false, rx.values[5], rx.values[6], rx.values[9], rx.values[12], disp.SemaphoreQB, disp.SemaphoreA1B, disp.SemaphoreA2B) end function ka.drawRxMini3(x, y) -- Empfängerspannung 3 local disp = variables.Rex.Display return ka.drawRx(x, y, "B", true, rx.values[5], rx.values[6], rx.values[9], rx.values[12], disp.SemaphoreQB, disp.SemaphoreA1B, disp.SemaphoreA2B) end function ka.drawMTAG(x, y) -- MTAG-Daten anzeigen local font, text, width, height height = 52 -- Kachelhöhe -- Hintergrundfarbe einstellen changeColorByIndex(variables.MTAG.iBgColor, 255) if variables.MTAG.iBgColor ~= 0 then drawKaBackground(x + 2, y + 0, 128, height) end setTextColorDependBG(43, 255, variables.MTAG.iBgColor) font = FONT_MINI text = trans.mtagLabel width = lcd.getTextWidth(font, text) lcd.drawText(x + 66 - width/2, y - 1, text, font) font = FONT_NORMAL lcd.drawText(x + 3, y + 8, trans.mtagState..":", font) lcd.drawText(x + 46, y + 8, trans.mtagCapa..":", font) lcd.drawText(x + 3, y + 22, trans.mtagId..":", font) lcd.drawText(x + 46, y + 22, trans.mtagCycles..":", font) lcd.drawText(x + 3, y + 36, trans.mtagcrate..":", font) lcd.drawText(x + 46, y + 36, trans.mtagCells..":", font) text = string.format("%d", variables.MTAG.iState) lcd.drawText(x + 21, y + 8, text, font) text = string.format("%d", variables.MTAG.iCapacity) lcd.drawText(x + 96, y + 8, text, font) text = string.format("%d", variables.MTAG.iAkkuID) lcd.drawText(x + 21, y + 22, text, font) text = string.format("%d", variables.MTAG.iCycles) lcd.drawText(x + 96, y + 22, text, font) text = string.format("%d", variables.MTAG.iCrate) lcd.drawText(x + 21, y + 36, text, font) text = string.format("%d", variables.MTAG.iAccOfCells) lcd.drawText(x + 96, y + 36, text, font) end function ka.drawKordinaten(x, y) -- GPS Koordinaten anzeigen local font, text, width, height height = 43 -- Hintergrundfarbe einstellen changeColorByIndex(variables.GPS.iBgColor, 255) if variables.GPS.iBgColor ~= 0 then drawKaBackground(x + 2, y + 0, 128, height) end setTextColorDependBG(43, 255, variables.GPS.iBgColor) font = FONT_MINI text = trans.kordinatena width = lcd.getTextWidth(font, text) lcd.drawText(x + 66 - width/2, y - 0, text, font) font = FONT_NORMAL lcd.drawText(x + 3, y + 10, "B:", font) lcd.drawText(x + 3, y + 26, "L:", font) local nesw = {"N", "E", "S", "W"} local latDeg = (variables.GPS.Breite >> 16) & 0xFF local lonDeg = (variables.GPS.Laenge >> 16) & 0xFF local latMin = (variables.GPS.Breite & 0xFFFF) * 0.001 local lonMin = (variables.GPS.Laenge & 0xFFFF) * 0.001 font = FONT_BIG text = string.format("%3d\u{B0}%2.3f'", latDeg, latMin) width = lcd.getTextWidth(font, text) lcd.drawText(x + 112 - width, y + 8, text, font) lcd.drawText(x + 112, y + 8, nesw[variables.GPS.iLatNachkomma + 1 ], font) text = string.format("%3d\u{B0}%2.3f'", lonDeg, lonMin) width = lcd.getTextWidth(font, text) lcd.drawText(x + 112 - width, y + 24, text, font) lcd.drawText(x + 112, y + 24, nesw[variables.GPS.iLonNachkomma + 1], font) end -- Hilfsprogramme für drawTelVal() -- ------------------------------- -- Glättung mit fließendem Mittelwert -- tv enthält das Speicherfeld -- actValue ist der zu glättende Eingangswert -- gValue ist der geglättete Ausgangswert local function Smothing(tv, actValue) local gValue = actValue -- geglätteter Wert, nur wenn Filter eingeschaltet ist local iPoint = tv.fValueFieldSmooth[1] -- Zeiger auf den aktuellen Speicher local fSum = 0.0 -- Summe für Mittelwertbildung if tv.bTVSmooth then -- Wert speichern tv.fValueFieldSmooth[iPoint] = actValue -- Mittelwert bilden for i=2, #tv.fValueFieldSmooth do fSum = fSum + tv.fValueFieldSmooth[i] end gValue = fSum / (#tv.fValueFieldSmooth - 1) -- Zeiger auf nächsten Speicher setzen iPoint = iPoint + 1 if iPoint > #tv.fValueFieldSmooth then iPoint = 2 end tv.fValueFieldSmooth[1] = iPoint end return gValue end -- Formatiert einen numerischen Wert mit der angegebenen Nachkommastellenzahl. -- nk=0 → "%d" (ganzzahlig), nk=1 → "%.1f", nk=2 → "%.2f", nk=3 → "%.3f" local function fmtByDecimals(nk, value) nk = math.floor(nk + 0.5) -- Integer-Absicherung (typisches LUA 3.5 Problem) if nk <= 0 then return string.format("%d", value) end return string.format("%." .. nk .. "f", value) end -- Berechnet die X-Position für horizontale Ausrichtung innerhalb eines Widgets. -- align: 1=linksbündig, 2=mittig, 3=rechtsbündig -- padding: optionaler Innenabstand (Standard: 3px) local function alignX(iXpos, align, totalW, textW, padding) padding = padding or 3 if align == 1 then return iXpos + padding end if align == 2 then return iXpos + (totalW - textW) / 2 end if align == 3 then return iXpos + totalW - textW end return iXpos + padding end -- Steuert die Blink-Zustandsmaschine für Warn-/Alarm-Anzeigen. -- Erste Zyklushälfte: Hintergrund gefärbt (sichtbar). -- Zweite Zyklushälfte: Hintergrund normal (unsichtbar). -- bgColorIdx : Farbindex Hintergrund (23=rot, 26=gelb) -- negColorIdx: Farbindex für negative Werte (23=rot, 43=schwarz) local function handleBlinkState(tv, x, y, bgColorIdx, negColorIdx) if tv.iLimBlinken == 0 then tv.iLimBlinken = 1 end local halfFreq = tv.iLimBlinkenFreqZael / 2 if tv.iLimBlinken >= 0 and tv.iLimBlinken <= halfFreq then changeColorByIndex(bgColorIdx, 255) drawKaBackground(x + 2, y + 0, tv.iTelValWidth, tv.iTelValHeight) tv.iLimBlinken = tv.iLimBlinken + 1 -- keine gleiche Farbe if bgColorIdx ~= negColorIdx then tv.sTxColDrawNo = setTextColorDependBG(negColorIdx, 255, bgColorIdx) else tv.sTxColDrawNo = setTextColorDependBG(43, 255, bgColorIdx) end elseif tv.iLimBlinken <= tv.iLimBlinkenFreqZael then tv.iLimBlinken = tv.iLimBlinken + 1 else tv.iLimBlinken = 1 end end -- Zeichnet Min/Max als separate Texte (Max: rechtsbündig mittig, Min: unten). -- Verwendet bei Size 2 (Normaldarstellung). local function drawMinMaxSeparate(nk, tv, iXpos, iYpos, font) local height = lcd.getTextHeight(font) -- Max-Wert: rechtsbündig, vertikal mittig local sMax = fmtByDecimals(nk, tv.fTelValMax) local wMax = lcd.getTextWidth(font, sMax) lcd.drawText(iXpos + tv.iTelValWidth - 3 - wMax, iYpos + (tv.iTelValHeight - height) / 2, sMax, font) -- Min-Wert: rechtsbündig, unten local sMin = fmtByDecimals(nk, tv.fTelValMin) local wMin = lcd.getTextWidth(font, sMin) lcd.drawText(iXpos + tv.iTelValWidth - 3 - wMin, iYpos + tv.iTelValHeight - height, sMin, font) end -- Zeichnet Min/Max als einzeiligen Text, horizontal zentriert am unteren Rand. -- showUnit=true → "min: 12.3 V max: 45.6 V" (Size 4) -- showUnit=false → "min: 12.3 max: 45.6" (Size 3) local function drawMinMaxInline(nk, tv, iXpos, iYpos, font, showUnit) local sMin = fmtByDecimals(nk, tv.fTelValMin) local sMax = fmtByDecimals(nk, tv.fTelValMax) local unit = showUnit and (" " .. tv.sTelValEinheit) or "" local text = string.format("min: %s%s max: %s%s", sMin, unit, sMax, unit) local w = lcd.getTextWidth(font, text) local h = lcd.getTextHeight(font) lcd.drawText(iXpos + (tv.iTelValWidth - w) / 2, iYpos + tv.iTelValHeight - h, text, font) end -- Prüft ob mindestens ein Text-Limit (fTVTxLim1–4) konfiguriert ist. local function hasTextLimits(tv) return tv.fTVTxLim1 ~= nil or tv.fTVTxLim2 ~= nil or tv.fTVTxLim3 ~= nil or tv.fTVTxLim4 ~= nil end -- Wählt den passenden Text zu einem Limit-Schwellenwert. -- Priorität: Limit1 > Limit2 > Limit3 > Limit4 > Typ10-Fallback > Message3 local function selectLimitText(tv, sensorType, fallbackText) local limits = { { tv.fTVTxLim1, tv.sTVTxText1 }, { tv.fTVTxLim2, tv.sTVTxText2 }, { tv.fTVTxLim3, tv.sTVTxText3 }, { tv.fTVTxLim4, tv.sTVTxText4 }, } for _, pair in ipairs(limits) do if pair[1] ~= nil and tv.fTelValAct == pair[1] then return pair[2] end end if sensorType == 10 then return fallbackText end return trans.menu_TelValMessage3 end -- Zeichnet einen Text horizontal und vertikal zentriert im Widget. -- Verwendet für Fehlermeldungen bei GPS/Flüge/Countdown in Size 3/4. local function drawCenteredError(tv, iXpos, iYpos, fontF, msgText) local w = lcd.getTextWidth(fontF, msgText) local h = lcd.getTextHeight(fontF) lcd.drawText(iXpos + 1 + (tv.iTelValWidth - w) / 2, iYpos + (tv.iTelValHeight - h) / 2, msgText, fontF) end -- Zeichnet den Header-Text mit der konfigurierten Ausrichtung. -- yPos: die Y-Koordinate für den Header local function drawHeaderAligned(tv, iXpos, font, headerText, yPos) local w = lcd.getTextWidth(font, headerText) local xH = alignX(iXpos, tv.iTelValAllignmentHorizontal, tv.iTelValWidth, w) lcd.drawText(xH, yPos, headerText, font) end -- Steuert die Sprachausgabe des aktuellen Sensorwertes. -- Die Ansage wird durch einen Schalter (Switch) ausgelöst und durch -- ein Semaphor-Flag geschützt, damit der Wert nicht mehrfach -- gleichzeitig angesagt wird. local function handlePlaybackTV(tv) local iActTime = system.getTime() -- Kommando liegt an if tv.bCommandPlay then -- Zeitstufe starten if (tv.iLockNewPlay == 0) then tv.bSemaPlay = false -- Neue Ausgabe freigegeben tv.iLockNewPlay = iActTime + 3 -- 3 Sekunden Verzögerungszeit für anstehendes Kommando -- Prüfen, ob die Zeitstufe abgelaufen ist elseif (iActTime >= tv.iLockNewPlay) then tv.bCommandPlay = false -- Zeitstufe abgelaufen Kommando löschen tv.iLockNewPlay = 0 end -- Ansage ausführen: Kommando steht an UND Semaphor nicht gesetzt UND kein anderes Audio läuft if not system.isPlayback() then if not tv.bSemaPlay then tv.bSemaPlay = true -- Sperre: Keine neue Auagabe -- Wert mit physikalischer Einheit ansagen system.playNumber(tv.fTelValAct, tv.iTelValNachkomma, tv.sTelValEinheit) end end end end local function drawTelVal(x, y, iActTelVal) local text, font, fontUnit, fontFehler, fontValue local width, height, widthValue, heightValue local zeile, zeileShort, textValue local iXpos, iYpos local bFehler = false local SensorWert = {} local bNoMinMaxAnzeige = false local bNoUnitDisplay = false local bDrawGPS = false local iXoffset, iYoffset = 0, 0 local bTextAusgabe = false local sColorDependBG = "Black" -- schwarz = Standard local iTimerBeepNegative = -1 -- Zeilen-Keys berechnen zeile = string.format("iTVInst%d", iActTelVal) zeileShort = string.format("TV%d", iActTelVal) -- Lokaler Alias für TelVal[zeile] (Performance + Lesbarkeit) local tv = TelVal[zeile] font = FONT_MINI fontFehler = FONT_MINI -- Hintergrundfarbe einstellen changeColorByIndex(tv.iTelValBgColor, 255) if tv.iTelValBgColor ~= 0 then drawKaBackground(x + 2, y + 0, tv.iTelValWidth, tv.iTelValHeight) end iXpos = x iYpos = y -- Auf sicheren Wert initialisieren tv.fTelValAct = 0.0 -- Geber prüfen local swValue = system.getInputsVal(tv.swTelVal) if swValue ~= nil then tv.sTelValSensor = "Geber" tv.iTelValSensorID = 1 tv.fTelValAct = swValue * 100.0 end -- Kein Sensor projektiert → Meldung anzeigen if tv.iTelValSensorID == 0 then setTextColorDependBG(43, 255, tv.iTelValBgColor) text = trans.menu_TelValMessage width = lcd.getTextWidth(FONT_MINI, text) height = lcd.getTextHeight(FONT_MINI) lcd.drawText(iXpos + (tv.iTelValWidth - width) / 2, iYpos + tv.iTelValHeight / 2, text, FONT_MINI) text = string.format("TeleValue %d", tv.iTelValNo) width = lcd.getTextWidth(FONT_MINI, text) height = lcd.getTextHeight(FONT_MINI) lcd.drawText(iXpos + (tv.iTelValWidth - width) / 2, iYpos + tv.iTelValHeight / 2 - height, text, FONT_MINI) else -- Sensorwertausgabe -- ══════════════════ -- Sensorwert laden if tv.sTelValSensor == "Geber" then SensorWert.value = tv.fTelValAct SensorWert.type = 0 else if tv.iTelValSensorType == 2 then -- Interner / Sender Sensor SensorWert = variables.Sensors[tv.iTelValParamIdx] else -- Externer / Receiver Sensor text = tv.sTelValSensor if string.find(text, "REX") ~= nil and TelVal.iREXoffset > 0 then SensorWert = system.getSensorValueByID( tv.iTelValSensorID, tv.iTelValParamNo - 1 + TelVal.iREXoffset) elseif tv.bTelValSensorNoName == true then SensorWert = system.getSensorByID( tv.iTelValSensorID, tv.iTelValParamNo - 2) elseif string.find(text, "Spirit") ~= nil and tv.iTelValParamNo == 4 then SensorWert = system.getSensorByID( tv.iTelValSensorID, tv.iTelValParamNo - 2 + 7) else SensorWert = system.getSensorByID( tv.iTelValSensorID, tv.iTelValParamNo - 1) end end end -- REX-Fallback: Offset ermitteln falls SensorWert nil if SensorWert == nil then text = tv.sTelValSensor if string.find(text, "REX") ~= nil then if TelVal.iREXoffset == 0 then for i = 1, 50 do SensorWert = system.getSensorValueByID(tv.iTelValSensorID, i) if SensorWert ~= nil then TelVal.iREXoffset = i - 1 break else TelVal.iREXoffset = 13 end end end SensorWert = system.getSensorByID( tv.iTelValSensorID, tv.iTelValParamNo - 1 + TelVal.iREXoffset) end end -- Sensorwert vorhanden → Typprüfung und Textaufbereitung if SensorWert ~= nil then tv.sTxColDrawNo = setTextColorDependBG(43, 255, tv.iTelValBgColor) -- Typ 5: Datum/Zeit -- ══════════════════ if SensorWert.type == 5 then if SensorWert.decimals == 0 then -- Zeit if SensorWert.valHour ~= nil and SensorWert.valMin ~= nil and SensorWert.valSec ~= nil then if SensorWert.valHour == 0 then if not SensorWert.valSign then bNoUnitDisplay = false textValue = string.format(" %02d:%02d ", SensorWert.valMin, SensorWert.valSec) else bNoUnitDisplay = true tv.sTxColDrawNo = setTextColorDependBG(23, 255, tv.iTelValBgColor) textValue = string.format(" -%02d:%02d ", SensorWert.valMin, SensorWert.valSec) end else bNoUnitDisplay = true if not SensorWert.valSign then textValue = string.format("%02d:%02d:%02d", SensorWert.valHour, SensorWert.valMin, SensorWert.valSec) else tv.sTxColDrawNo = setTextColorDependBG(23, 255, tv.iTelValBgColor) textValue = string.format("-%02d:%02d:%02d", SensorWert.valHour, SensorWert.valMin, SensorWert.valSec) end end tv.iTelValTxColor = SensorWert.valTxColor tv.sTelValActText = textValue bNoMinMaxAnzeige = true else textValue = string.format("TV%d: invalid Values", iActTelVal) bFehler = true end else -- Datum if SensorWert.valYear ~= nil and SensorWert.valMonth ~= nil and SensorWert.valDay ~= nil then textValue = string.format("%02d-%02d-%02d", SensorWert.valYear - 2000, SensorWert.valMonth, SensorWert.valDay) tv.sTxColDrawNo = setTextColorDependBG(43, 255, tv.iTelValBgColor) tv.sTelValActText = textValue bNoMinMaxAnzeige = true else textValue = string.format("TV%d: invalid Values", iActTelVal) bFehler = true end end -- Typ 9: GPS Koordinaten -- ═══════════════════════ elseif SensorWert.type == 9 then if SensorWert.decimals ~= nil and SensorWert.valGPS ~= nil then local nesw = {"N", "E", "S", "W"} local minutes = (SensorWert.valGPS & 0xFFFF) * 0.001 local degs = (SensorWert.valGPS >> 16) & 0xFF textValue = string.format("%d°%2.3f'%s", degs, minutes, nesw[SensorWert.decimals + 1]) tv.sTelValActText = textValue bNoMinMaxAnzeige = true bDrawGPS = true else tv.sTxColDrawNo = setTextColorDependBG(43, 255, tv.iTelValBgColor) textValue = string.format("TV%d: %s = invalid", iActTelVal, SensorWert.label) bFehler = true end -- Typ 10: Flügeanzeige -- ════════════════════ elseif SensorWert.type == 10 then if SensorWert.valTotal ~= nil and SensorWert.valToday ~= nil then if tv.iTelValSize == 0 or tv.iTelValSize == 1 then textValue = string.format("%s %d : %d", trans.TxSensor_Flights, SensorWert.valToday, SensorWert.valTotal) elseif tv.iTelValSize == 2 then textValue = string.format(" %d:%d ", SensorWert.valToday, SensorWert.valTotal) end tv.sTelValActText = textValue bNoMinMaxAnzeige = true else -- print(string.format("%s : %s", SensorWert.valToday, SensorWert.valTotal)) tv.sTxColDrawNo = setTextColorDependBG(43, 255, tv.iTelValBgColor) textValue = string.format("TV%d: %s = invalid", iActTelVal, SensorWert.label) bFehler = true end -- Typ 11: Countdownanzeige -- ═════════════════════════ elseif SensorWert.type == 11 then tv.iTelValTxColor = SensorWert.valTxColor ~= nil and 23 or nil local time = SensorWert.valMin * 60 + SensorWert.valSec if timeVars.cTime and math.ceil(timeVars.cTime) < 0 then time = -time end -- Textfarbe nach Restzeit bestimmen if time <= 60 then tv.iTelValTxColor = 23 tv.sTxColDrawNo = setTextColorDependBG(23, 255, tv.iTelValBgColor) elseif time <= 0.5 * (60 * se.countdownMin + se.countdownSec) then tv.iTelValTxColor = se.color and nil or 29 else tv.iTelValTxColor = se.color and 29 or nil end local sVorzeichen = time < 0 and "-" or " " if SensorWert.valHour == 0 then textValue = string.format("%s%02d:%02d ", sVorzeichen, SensorWert.valMin, SensorWert.valSec) else textValue = string.format("%s%02d:%02d:%02d", sVorzeichen, SensorWert.valHour, SensorWert.valMin, SensorWert.valSec) end tv.sTelValActText = textValue bNoMinMaxAnzeige = true -- Typ 12: Betriebsstunden: Stunden:Minuten -- ═════════════════════════════════════════ elseif SensorWert.type == 12 then -- Zeit if SensorWert.valHour ~= nil and SensorWert.valMin ~= nil then bNoUnitDisplay = false textValue = string.format(" %02d:%02d ", SensorWert.valHour, SensorWert.valMin) tv.iTelValTxColor = SensorWert.valTxColor tv.sTelValActText = textValue bNoMinMaxAnzeige = true else textValue = string.format("TV%d: invalid Values", iActTelVal) bFehler = true end -- Typ 13: Timer Beep: (Stunden:)Minuten:Sekungen mit Farbe -- ═══════════════════════════════════════════════ elseif SensorWert.type == 13 then -- Zeit if SensorWert.valHour ~= nil and SensorWert.valMin ~= nil and SensorWert.valSec ~= nil then if SensorWert.valHour == 0 then if not SensorWert.valSign then bNoUnitDisplay = false textValue = string.format(" %02d:%02d ", SensorWert.valMin, SensorWert.valSec) iTimerBeepNegative = 1 else bNoUnitDisplay = true tv.sTxColDrawNo = setTextColorDependBG(23, 255, tv.iTelValBgColor) textValue = string.format(" -%02d:%02d ", SensorWert.valMin, SensorWert.valSec) iTimerBeepNegative = -1 end else bNoUnitDisplay = true if not SensorWert.valSign then textValue = string.format("%02d:%02d:%02d", SensorWert.valHour, SensorWert.valMin, SensorWert.valSec) else tv.sTxColDrawNo = setTextColorDependBG(23, 255, tv.iTelValBgColor) textValue = string.format("-%02d:%02d:%02d", SensorWert.valHour, SensorWert.valMin, SensorWert.valSec) end end if variables.BeepCmd.iState > 1 then tv.iTelValTxColor = SensorWert.valTxColor if tv.iTelValBgColorMem == nil then tv.iTelValBgColorMem = tv.iTelValBgColor -- merken zum Zurückschalten, wenn Timer Beep abgelaufen ist end tv.iTelValBgColor = SensorWert.valBgColor changeColorByIndex(SensorWert.valBgColor, 255) drawKaBackground(x + 2, y + 0, tv.iTelValWidth, tv.iTelValHeight) changeColorByIndex(tv.iTelValTxColor, 255) else if tv.iTelValBgColorMem ~= nil then tv.iTelValBgColor = tv.iTelValBgColorMem -- Zurückschalten der Hintergrundfarbe tv.iTelValBgColorMem = nil -- nur einmal changeColorByIndex(tv.iTelValBgColor, 255) if tv.iTelValBgColor ~= 0 then drawKaBackground(x + 2, y + 0, tv.iTelValWidth, tv.iTelValHeight) end end end tv.sTelValActText = textValue bNoMinMaxAnzeige = true else textValue = string.format("TV%d: invalid Values", iActTelVal) bFehler = true end -- Normaler Sensorwert -- ════════════════════ else tv.fTelValAct = SensorWert.value if tv.fTelValAct ~= nil then tv.fTelValAct = tv.fTelValAct * tonumber(tv.sTelValKorrekturfaktor) else tv.fTelValAct = 0.0 end -- Glättung tv.fTelValAct = Smothing(tv, tv.fTelValAct) -- Sprachausgabe des Sensorwertes (bei Schalterdruck) handlePlaybackTV(tv) -- Textfarbe für negative und normale Werte if tv.fTelValAct < 0.0 then tv.sTxColDrawNo = setTextColorDependBG(23, 255, tv.iTelValBgColor) else tv.sTxColDrawNo = setTextColorDependBG(43, 255, tv.iTelValBgColor) end -- Min/Max aktualisieren und persistent speichern if tv.fTelValAct > tv.fTelValMax then tv.fTelValMax = tv.fTelValAct --system.pSave(zeileShort .. "vmax", tv.fTelValMax) elseif tv.fTelValAct < tv.fTelValMin then tv.fTelValMin = tv.fTelValAct --system.pSave(zeileShort .. "vmin", tv.fTelValMin) end -- Wert-Text formatieren textValue = fmtByDecimals(tv.iTelValNachkomma, tv.fTelValAct) end if variables.bLimitWatchReleased then -- Überwachung freigegeben -- Warnung/Alarm → Blink-Logik (Wachsend) -- ═══════════════════════════════════════ local act = tv.fTelValAct if tv.fLimGrowAlarm ~= nil and act >= tv.fLimGrowAlarm then handleBlinkState(tv, x, y, 23, 23) -- Alarm: rot/rot elseif tv.fLimGrowWarning ~= nil and act >= tv.fLimGrowWarning then handleBlinkState(tv, x, y, 26, 43) -- Warnung: gelb/rot elseif tv.fLimGrowWarning ~= nil and act < tv.fLimGrowWarning and tv.iLimBlinken == 1 then tv.iLimBlinken = 0 end -- Warnung/Alarm → Blink-Logik (Schrumpfend) -- ══════════════════════════════════════════ if tv.fLimShrkAlarm ~= nil and act <= tv.fLimShrkAlarm then handleBlinkState(tv, x, y, 23, 43) -- Alarm: rot/schwarz elseif tv.fLimShrkWarning ~= nil and act <= tv.fLimShrkWarning then handleBlinkState(tv, x, y, 26, 43) -- Warnung: gelb/rot elseif tv.fLimGrowWarning ~= nil and act > tv.fLimGrowWarning and tv.iLimBlinken == 1 then tv.iLimBlinken = 0 end end -- SIZE 0: Ausgabe Klein -- ══════════════════════ if tv.iTelValSize == 0 then font = FONT_MINI if SensorWert.type == 9 or SensorWert.type == 12 then --GPS ohne Einheit text = string.format("%s", textValue) else text = string.format("%s %s", textValue, tv.sTelValEinheit) end iYpos = iYpos + 1 -- getestet für bessere Lesbarkeit if SensorWert.type == 10 then -- Flüge: Spezialtext mittig text = string.format("%s", tv.sTelValActText) widthValue = lcd.getTextWidth(font, text) heightValue = lcd.getTextHeight(font) x = iXpos + (tv.iTelValWidth - 3 - widthValue) / 2 y = iYpos + (tv.iTelValHeight - heightValue) / 2 lcd.drawText(x, y, text, FONT_MINI) else widthValue = lcd.getTextWidth(font, text) heightValue = lcd.getTextHeight(font) if tv.iTelValAllignmentHorizontal == 3 then -- Wert linksbündig, Header rechtsbündig x = iXpos + 4 y = iYpos + (tv.iTelValHeight - heightValue) / 2 lcd.drawText(x, y, text, FONT_MINI) -- Header text = tv.sTelValHeader width = lcd.getTextWidth(FONT_MINI, text) lcd.drawText(iXpos + tv.iTelValWidth - width - 1, iYpos + (tv.iTelValHeight - lcd.getTextHeight(FONT_MINI)) / 2, text, FONT_MINI) else -- Wert rechtsbündig, Header linksbündig x = iXpos + tv.iTelValWidth - widthValue y = iYpos + (tv.iTelValHeight - heightValue) / 2 lcd.drawText(x, y, text, FONT_MINI) -- Header text = tv.sTelValHeader height = lcd.getTextHeight(FONT_MINI) lcd.drawText(iXpos + 4, iYpos + (tv.iTelValHeight - height) / 2, text, FONT_MINI) end end -- SIZE 1: Ausgabe Klein/Normal -- ═════════════════════════════ elseif tv.iTelValSize == 1 then font = FONT_NORMAL -- Textausgabe prüfen if hasTextLimits(tv) or SensorWert.type == 10 then bTextAusgabe = true font = FONT_BOLD text = selectLimitText(tv, SensorWert.type, textValue) elseif SensorWert.type == 9 or SensorWert.type == 12 then --GPS ohne Einheit bTextAusgabe = false font = FONT_BIG text = string.format("%s", textValue) -- ohne Einheit else bTextAusgabe = false text = string.format("%s %s", textValue, tv.sTelValEinheit) end -- Font verkleinern falls zu breit if lcd.getTextWidth(font, text) > tv.iTelValWidth then font = FONT_MINI end widthValue = lcd.getTextWidth(font, text) heightValue = lcd.getTextHeight(font) if tv.iTelValAllignmentHorizontal == 3 then -- Wert links/mittig, Header rechts x = bTextAusgabe and iXpos + (tv.iTelValWidth - widthValue) / 2 or iXpos + 4 y = iYpos + (tv.iTelValHeight - heightValue) / 2 lcd.drawText(x, y, text, font) if not bTextAusgabe then -- Header rechtsbündig text = tv.sTelValHeader width = lcd.getTextWidth(FONT_MINI, text) iYpos = iYpos + 1 -- getestet für bessere Lesbarkeit lcd.drawText(iXpos + tv.iTelValWidth - width -1, iYpos + (tv.iTelValHeight - lcd.getTextHeight(FONT_MINI)) / 2, text, FONT_MINI) end else -- Wert rechts/mittig, Header links x = bTextAusgabe and iXpos + (tv.iTelValWidth - widthValue) / 2 or iXpos + tv.iTelValWidth - widthValue y = iYpos + (tv.iTelValHeight - heightValue) / 2 lcd.drawText(x, y, text, font) if not bTextAusgabe then -- Header linksbündig text = tv.sTelValHeader height = lcd.getTextHeight(FONT_MINI) iYpos = iYpos + 1 -- getestet für bessere Lesbarkeit lcd.drawText(iXpos + 4, iYpos + (tv.iTelValHeight - height) / 2, text, FONT_MINI) end end -- SIZE 2: Ausgabe Normal (Wert + Einheit + Min/Max) -- ══════════════════════════════════════════════════ elseif tv.iTelValSize == 2 then if hasTextLimits(tv) then -- ── Textausgabe (Limit-Texte) ── bTextAusgabe = true text = selectLimitText(tv, SensorWert.type, textValue) -- Font-Fallback-Kette: MAXI → BOLD → MINI → "zu lang" fontValue = FONT_MAXI widthValue = lcd.getTextWidth(fontValue, text) y = iYpos + tv.iTelValHeight - lcd.getTextHeight(fontValue) + 7 - iYoffset if widthValue > tv.iTelValWidth then fontValue = FONT_BOLD widthValue = lcd.getTextWidth(fontValue, text) y = iYpos + (tv.iTelValHeight - lcd.getTextHeight(fontValue)) / 2 + 4 if widthValue > tv.iTelValWidth then fontValue = FONT_MINI widthValue = lcd.getTextWidth(fontValue, text) y = iYpos + (tv.iTelValHeight - lcd.getTextHeight(fontValue)) / 2 + 5 if widthValue > tv.iTelValWidth then text = trans.menu_TextZuLang widthValue = lcd.getTextWidth(fontValue, text) end end end x = iXpos + (tv.iTelValWidth - widthValue) / 2 lcd.drawText(x, y, text, fontValue) else -- ── Normale Wertausgabe ── font = FONT_MAXI fontValue = FONT_MAXI fontUnit = FONT_NORMAL if bDrawGPS then font = FONT_NORMAL fontValue = FONT_BIG fontUnit = FONT_MINI iXoffset = 5 iYoffset = -5 + tv.iTelValHeight / 2 end -- Wert zeichnen widthValue = lcd.getTextWidth(fontValue, textValue) heightValue = lcd.getTextHeight(fontValue) x = iXpos + 3 y = iYpos + tv.iTelValHeight - heightValue + 6 - iYoffset if not bFehler then lcd.drawText(x, y, textValue, fontValue) else widthValue = lcd.getTextWidth(fontFehler, textValue) lcd.drawText(x, y, textValue, fontFehler) end -- Einheit zeichnen if not bNoUnitDisplay then width = lcd.getTextWidth(fontUnit, tv.sTelValEinheit) height = lcd.getTextHeight(fontUnit) lcd.drawText(iXpos + widthValue + 3 + iXoffset, iYpos + tv.iTelValHeight - height + 1 - iYoffset, tv.sTelValEinheit, fontUnit) end -- Min/Max zeichnen (separate Darstellung) if not bNoMinMaxAnzeige then drawMinMaxSeparate(tv.iTelValNachkomma, tv, iXpos, iYpos, FONT_MINI) end end -- Überschrift if tv.sTelValHeader == "" or tv.sTelValHeader == nil then text = tv.sTelValName else text = tv.sTelValHeader end font = FONT_MINI width = lcd.getTextWidth(font, text) x = alignX(iXpos, tv.iTelValAllignmentHorizontal, tv.iTelValWidth - 3, width) lcd.drawText(x, iYpos - 0, text, font) -- SIZE 3: Ausgabe Big / Groß (drawNumber) -- ════════════════════════════════════════ elseif tv.iTelValSize == 3 then x = iXpos + tv.iTelValWidth y = iYpos + 17 if not bFehler and not bDrawGPS and SensorWert.type ~= 10 and SensorWert.type ~= 11 and SensorWert.type ~= 12 and SensorWert.type ~= 13 then local digi = tonumber(string.format("%d", tv.iTelValNachkomma)) local iXoffset = 4 local nrWidth = getNumberWidth(tv.fTelValAct, digi, 1) -- Textfarbe setzen if tv.fTelValAct < 0.0 then --colorNumber = "Red" sColorDependBG = setTextColorDependBG(23, 255, tv.iTelValBgColor) elseif variables.Collect.textInverse then --colorNumber = "White" sColorDependBG = setTextColorDependBG(44, 255, tv.iTelValBgColor) else --colorNumber = "Black" sColorDependBG = setTextColorDependBG(43, 255, tv.iTelValBgColor) end if(nrWidth < tv.iTelValWidth) then x = iXpos + iXoffset + (tv.iTelValWidth - nrWidth ) / 2 -- zentriert y = iYpos + (tv.iTelValHeight - getNumberHeight(1) ) / 2 --zentriert drawNumber(x, y, tv.fTelValAct, digi, sColorDependBG, 1) else fontValue = FONT_MAXI widthValue = lcd.getTextWidth(fontValue, textValue) heightValue = lcd.getTextHeight(fontValue) x = iXpos + (tv.iTelValWidth - widthValue) / 2 y = iYpos + (tv.iTelValHeight - heightValue) / 2 lcd.drawText(x, y, textValue, fontValue) end elseif not bFehler and not bDrawGPS and SensorWert.type == 13 then -- Timer Beep darstellen -- Textfarbe setzen if iTimerBeepNegative < 0.0 then --colorNumber = "Red" sColorDependBG = setTextColorDependBG(23, 255, tv.iTelValBgColor) elseif variables.Collect.textInverse then --colorNumber = "White" sColorDependBG = setTextColorDependBG(44, 255, tv.iTelValBgColor) else --colorNumber = "Black" sColorDependBG = setTextColorDependBG(43, 255, tv.iTelValBgColor) end local nrWidth = getNumberWidth(neg, 1, 1, textValue) --print(textValue.." "..nrWidth) if(nrWidth < tv.iTelValWidth) then x = iXpos + iXoffset + (tv.iTelValWidth - nrWidth ) / 2 y = iYpos + (tv.iTelValHeight - getNumberHeight(1) ) / 2 drawNumber(x, y, 0, 0, sColorDependBG, 1, textValue) else fontValue = FONT_MAXI widthValue = lcd.getTextWidth(fontValue, textValue) heightValue = lcd.getTextHeight(fontValue) x = iXpos + (tv.iTelValWidth - widthValue) / 2 y = iYpos + (tv.iTelValHeight - heightValue) / 2 lcd.drawText(x, y, textValue, fontValue) end else -- Fehlermeldung zentriert if bDrawGPS then drawCenteredError(tv, iXpos, iYpos, fontFehler, trans.menu_TelValMessage2) elseif SensorWert.type == 10 or SensorWert.type == 11 then drawCenteredError(tv, iXpos, iYpos, fontFehler, trans.menu_TelValMessage4) end end -- Min/Max inline (ohne Einheit) if not bNoMinMaxAnzeige then drawMinMaxInline(tv.iTelValNachkomma, tv, iXpos, iYpos, FONT_MINI, false) end -- Header mit Einheit text = string.format("%s [%s]", tv.sTelValHeader, tv.sTelValEinheit) width = lcd.getTextWidth(FONT_MINI, text) x = alignX(iXpos, tv.iTelValAllignmentHorizontal, tv.iTelValWidth, width) lcd.drawText(x, iYpos + 1, text, FONT_MINI) -- SIZE 4: Ausgabe Gigantisch (drawNumber groß) -- ═════════════════════════════════════════════ elseif tv.iTelValSize == 4 then x = iXpos + tv.iTelValWidth y = iYpos + tv.iTelValHeight / 2 - 34 if not bFehler and not bDrawGPS and SensorWert.type ~= 5 and SensorWert.type ~= 10 and SensorWert.type ~= 11 and SensorWert.type ~= 12 and SensorWert.type ~= 13 then local digi = tonumber(string.format("%d", tv.iTelValNachkomma)) local iXoffset = 4 local nrWidth = getNumberWidth(tv.fTelValAct, digi, 5) -- Textfarbe setzen if tv.fTelValAct < 0.0 then --colorNumber = "Red" sColorDependBG = setTextColorDependBG(23, 255, tv.iTelValBgColor) elseif variables.Collect.textInverse then --colorNumber = "White" sColorDependBG = setTextColorDependBG(44, 255, tv.iTelValBgColor) else --colorNumber = "Black" sColorDependBG = setTextColorDependBG(43, 255, tv.iTelValBgColor) end if(nrWidth < tv.iTelValWidth) then x = iXpos + iXoffset + (tv.iTelValWidth - nrWidth ) / 2 -- zentriert y = iYpos + (tv.iTelValHeight - getNumberHeight(5) ) / 2 --zentriert drawNumber(x, y, tv.fTelValAct, digi, sColorDependBG, 5) else nrWidth = getNumberWidth(tv.fTelValAct, digi, 4) if(nrWidth < tv.iTelValWidth) then x = iXpos + iXoffset + (tv.iTelValWidth - nrWidth ) / 2 y = iYpos + (tv.iTelValHeight - getNumberHeight(4) ) / 2 drawNumber(x, y, tv.fTelValAct, digi, sColorDependBG, 4) else nrWidth = getNumberWidth(tv.fTelValAct, digi, 3) if(nrWidth < tv.iTelValWidth) then x = iXpos + iXoffset + (tv.iTelValWidth - nrWidth ) / 2 y = iYpos + (tv.iTelValHeight - getNumberHeight(3) ) / 2 drawNumber(x, y, tv.fTelValAct, digi, tv.sTxColDrawNo, 3) else nrWidth = getNumberWidth(tv.fTelValAct, digi, 2) if(nrWidth < tv.iTelValWidth) then x = iXpos + iXoffset + (tv.iTelValWidth - nrWidth ) / 2 y = iYpos + (tv.iTelValHeight - getNumberHeight(2) ) / 2 drawNumber(x, y, tv.fTelValAct, digi, sColorDependBG, 2) else nrWidth = getNumberWidth(tv.fTelValAct, digi, 1) x = iXpos + iXoffset + (tv.iTelValWidth - nrWidth ) / 2 y = iYpos + (tv.iTelValHeight - getNumberHeight(1) ) / 2 drawNumber(x, y, tv.fTelValAct, digi, sColorDependBG, 1) end end end end elseif not bFehler and not bDrawGPS and (SensorWert.type == 5 or SensorWert.type == 11 or SensorWert.type == 12 or SensorWert.type == 13 )then -- Timer Beep darstellen -- Textfarbe setzen if iTimerBeepNegative < 0.0 then --colorNumber = "Red" sColorDependBG = setTextColorDependBG(23, 255, tv.iTelValBgColor) elseif variables.Collect.textInverse then --colorNumber = "White" sColorDependBG = setTextColorDependBG(44, 255, tv.iTelValBgColor) else --colorNumber = "Black" sColorDependBG = setTextColorDependBG(43, 255, tv.iTelValBgColor) end local nrWidth = getNumberWidth(iTimerBeepNegative, 1, 5, textValue) if(nrWidth < tv.iTelValWidth) then x = iXpos + iXoffset + (tv.iTelValWidth - nrWidth ) / 2 y = iYpos + (tv.iTelValHeight - getNumberHeight(5) ) / 2 drawNumber(x, y, 0, 0, sColorDependBG, 5, textValue) else nrWidth = getNumberWidth(iTimerBeepNegative, 1, 4, textValue) if(nrWidth < tv.iTelValWidth) then x = iXpos + iXoffset + (tv.iTelValWidth - nrWidth ) / 2 y = iYpos + (tv.iTelValHeight - getNumberHeight(4) ) / 2 drawNumber(x, y, 0, 0, sColorDependBG, 4, textValue) else nrWidth = getNumberWidth(iTimerBeepNegative, 1, 3, textValue) if(nrWidth < tv.iTelValWidth) then x = iXpos + iXoffset + (tv.iTelValWidth - nrWidth ) / 2 y = iYpos + (tv.iTelValHeight - getNumberHeight(3) ) / 2 drawNumber(x, y, 0, 0, sColorDependBG, 3, textValue) else nrWidth = getNumberWidth(iTimerBeepNegative, 1, 2, textValue) if(nrWidth < tv.iTelValWidth) then x = iXpos + iXoffset + (tv.iTelValWidth - nrWidth ) / 2 y = iYpos + (tv.iTelValHeight - getNumberHeight(2) ) / 2 drawNumber(x, y, 0, 0, sColorDependBG, 2, textValue) else nrWidth = getNumberWidth(iTimerBeepNegative, 1, 1, textValue) if(nrWidth < tv.iTelValWidth) then x = iXpos + iXoffset + (tv.iTelValWidth - nrWidth ) / 2 y = iYpos + (tv.iTelValHeight - getNumberHeight(1) ) / 2 drawNumber(x, y, 0, 0, sColorDependBG, 1, textValue) else fontValue = FONT_MAXI widthValue = lcd.getTextWidth(fontValue, textValue) heightValue = lcd.getTextHeight(fontValue) x = iXpos + (tv.iTelValWidth - widthValue) / 2 y = iYpos + (tv.iTelValHeight - heightValue) / 2 lcd.drawText(x, y, textValue, fontValue) end end end end end else if bDrawGPS then drawCenteredError(tv, iXpos, iYpos, fontFehler, trans.menu_TelValMessage2) elseif SensorWert.type == 10 then drawCenteredError(tv, iXpos, iYpos, fontFehler, trans.menu_TelValMessage4) end end -- Min/Max inline (mit Einheit) if not bNoMinMaxAnzeige then drawMinMaxInline(tv.iTelValNachkomma, tv, iXpos, iYpos, FONT_NORMAL, true) end -- Header mit Einheit font = FONT_NORMAL text = string.format("%s [%s]", tv.sTelValHeader, tv.sTelValEinheit) width = lcd.getTextWidth(font, text) x = alignX(iXpos, tv.iTelValAllignmentHorizontal, tv.iTelValWidth, width) lcd.drawText(x, iYpos + 1, text, font) end else -- Sensor nicht erreichbar → Fehlermeldung -- ════════════════════════════════════════ text = tv.sTelValSensor setTextColorDependBG(43, 255, tv.iTelValBgColor) if string.find(text, "REX") ~= nil then text = string.format("TV=%d SID=%d No=%d", tv.iTelValNo, tv.iTelValSensorID, tv.iTelValParamNo - 1 + TelVal.iREXoffset) else text = string.format("TV=%d SID=%d No=%d", tv.iTelValNo, tv.iTelValSensorID, tv.iTelValParamNo - 1) end lcd.drawText(iXpos + 1, iYpos + 1, text, fontFehler) end end end function ka.drawTelVal1(x, y) drawTelVal(x, y, 1) -- Wert anzeigen end function ka.drawTelVal2(x, y) drawTelVal(x, y, 2) end function ka.drawTelVal3(x, y) drawTelVal(x, y, 3) end function ka.drawTelVal4(x, y) drawTelVal(x, y, 4) end function ka.drawTelVal5(x, y) drawTelVal(x, y, 5) end function ka.drawTelVal6(x, y) drawTelVal(x, y, 6) end function ka.drawTelVal7(x, y) drawTelVal(x, y, 7) end function ka.drawTelVal8(x, y) drawTelVal(x, y, 8) end function ka.drawTelVal9(x, y) drawTelVal(x, y, 9) end function ka.drawTelVal10(x, y) drawTelVal(x, y, 10) end function ka.drawTelVal11(x, y) drawTelVal(x, y, 11) end function ka.drawTelVal12(x, y) drawTelVal(x, y, 12) end function ka.drawTelVal13(x, y) drawTelVal(x, y, 13) end function ka.drawTelVal14(x, y) drawTelVal(x, y, 14) end function ka.drawTelVal15(x, y) drawTelVal(x, y, 15) end -- Erweiterung auf 24 TeleValues function ka.drawTelVal16(x, y) drawTelVal(x, y, 16) end function ka.drawTelVal17(x, y) drawTelVal(x, y, 17) end function ka.drawTelVal18(x, y) drawTelVal(x, y, 18) end function ka.drawTelVal19(x, y) drawTelVal(x, y, 19) end function ka.drawTelVal20(x, y) drawTelVal(x, y, 20) end function ka.drawTelVal21(x, y) drawTelVal(x, y, 21) end function ka.drawTelVal22(x, y) drawTelVal(x, y, 22) end function ka.drawTelVal23(x, y) drawTelVal(x, y, 23) end function ka.drawTelVal24(x, y) drawTelVal(x, y, 24) end -------------------------------------------------------------------------------- -- Hilfsfunktion: Bild laden mit Fehlerbehandlung und Change-Erkennung -- Kapselt die sich 4x wiederholende Lade-Logik in einer einzigen Funktion. -- Parameter: -- fp : Referenz auf FlexPics[zeile] -- imgKey : Schlüssel des Bildfeldes (z.B. "imgFlexPic1") -- fileKey : Schlüssel des Dateinamens (z.B. "sFlexPicFileName1") -- flagKey : Schlüssel des Changed-Flags (z.B. "bFlexPicChanged1") -------------------------------------------------------------------------------- local function loadFlexImage(fp, imgKey, fileKey, flagKey) if fp[imgKey] == nil then -- Erstmaliges Laden fp[imgKey] = loadImage(fp[fileKey]) if not fp[imgKey] then fp[imgKey] = loadImage("ErrorPic") fp[flagKey] = false end elseif fp[flagKey] == true then -- Bild existiert bereits, aber Dateiname hat sich geändert → neu laden fp[imgKey] = loadImage(fp[fileKey]) fp[flagKey] = false end end -------------------------------------------------------------------------------- -- Hilfsfunktion: Zustandsermittlung mit Hysterese -- Ersetzt die tief verschachtelte if-else-if Kette durch eine übersichtliche -- Zustandsmaschine. -- Parameter: -- fp : Referenz auf FlexPics[zeile] -------------------------------------------------------------------------------- local function updateFlexPicState(fp) local state = fp.iFlexPicState local value = fp.fFlexPicValue if state == 0 then -- Erstdarstellung → Zustand 2 (Mitte) als Default fp.iFlexPicState = 2 elseif state == 1 then -- Zustand 1: Prüfe ob nach oben gewechselt werden muss if value > fp.fFlexPicLim12 then fp.iFlexPicState = 2 -- Sprungprüfung: direkt weiter zu Zustand 3? if value > fp.fFlexPicLim23 then fp.iFlexPicState = 3 end end elseif state == 2 then -- Zustand 2: Prüfe Wechsel nach unten oder oben if value < fp.fFlexPicLim21 then fp.iFlexPicState = 1 elseif value > fp.fFlexPicLim23 then fp.iFlexPicState = 3 end elseif state == 3 then -- Zustand 3: Prüfe ob nach unten gewechselt werden muss if value < fp.fFlexPicLim32 then fp.iFlexPicState = 2 -- Sprungprüfung: direkt weiter zu Zustand 1? if value < fp["fFlexPicLim21"] then fp.iFlexPicState = 1 end end end end -------------------------------------------------------------------------------- -- Bild-Referenzen pro Zustand (Lookup statt if-else-if Kette) -------------------------------------------------------------------------------- local stateImageKeys = { [1] = "imgFlexPic1", [2] = "imgFlexPic2", [3] = "imgFlexPic3", } -------------------------------------------------------------------------------- -- Hauptfunktion: drawFlexPic -- Schnittstelle bleibt 100% identisch zum Original. -------------------------------------------------------------------------------- local function drawFlexPic(x, y, iActFlexPic) local text, font, width, height, iXpos, iYpos local zeile = string.format("iFlexPicIdx%d", iActFlexPic) local fp = FlexPics[zeile] -- Lokale Referenz → schnellerer Zugriff -- Pixel-Korrektur für mittlere Darstellung iXpos = (x == 132) and (x - 1) or x iYpos = y -- Eingabewert einlesen local FlexPic = system.getInputsVal(fp.swFlexPic) if FlexPic ~= nil then -- ── Wert umrechnen ────────────────────────────────────────── fp.fFlexPicValue = FlexPic * 100.0 -- ── Hintergrund ───────────────────────────────────────────── changeColorByIndex(fp.iFlexPicBgColor, 255) if fp.iFlexPicBgColor ~= 0 then drawKaBackground(x + 2, y, 128, fp.iFlexPicHeight) end setTextColorDependBG(43, 255, fp.iFlexPicBgColor) -- ── Alle 3 Bilder laden/aktualisieren ─────────────────────── loadFlexImage(fp, "imgFlexPic1", "sFlexPicFileName1", "bFlexPicChanged1") loadFlexImage(fp, "imgFlexPic2", "sFlexPicFileName2", "bFlexPicChanged2") loadFlexImage(fp, "imgFlexPic3", "sFlexPicFileName3", "bFlexPicChanged3") -- ── Zustandsmaschine aktualisieren ────────────────────────── updateFlexPicState(fp) -- ── Bild des aktuellen Zustands anzeigen ──────────────────── local imgKey = stateImageKeys[fp.iFlexPicState] if imgKey then lcd.drawImage(iXpos + 2, iYpos, fp[imgKey]) end -- ── Überschrift ermitteln ─────────────────────────────────── local header = fp.sFlexPicHeader if header == nil or header == "" then text = fp.sFlexPicName else text = header end -- ── Textposition berechnen ────────────────────────────────── font = FONT_MINI width = lcd.getTextWidth(font, text) height = lcd.getTextHeight(font) -- Horizontale Ausrichtung local hAlign = fp.iFlexPicAllignmentHorizontal if hAlign == 1 then x = iXpos + 3 -- linksbündig elseif hAlign == 2 then x = iXpos + 66 - width / 2 -- mittig elseif hAlign == 3 then x = iXpos + 128 - width -- rechtsbündig end -- Vertikale Ausrichtung local vAlign = fp.iFlexPicAllignmentVertikal if vAlign == 1 then y = iYpos - 1 -- oben elseif vAlign == 2 then y = iYpos + 1 + (fp.iFlexPicHeight - height) / 2 -- mittig elseif vAlign == 3 then y = iYpos + 1 + fp.iFlexPicHeight - height -- unten end -- Text ausgeben lcd.drawText(x, y, text, font) else -- ── Kein Schalter/Geber → Modellbild (Zustand 2) anzeigen ── loadFlexImage(fp, "imgFlexPic2", "sFlexPicFileName2", "bFlexPicChanged2") lcd.drawImage(iXpos + 2, iYpos, fp.imgFlexPic2) end end function ka.drawFlexPic1(x, y) drawFlexPic(x, y, 1) -- Bilder zeichnen end function ka.drawFlexPic2(x, y) drawFlexPic(x, y, 2) -- Bilder zeichnen end function ka.drawFlexPic3(x, y) drawFlexPic(x, y, 3) -- Bilder zeichnen end function ka.drawFlexPic4(x, y) drawFlexPic(x, y, 4) -- Bilder zeichnen end function ka.drawFlexPic5(x, y) drawFlexPic(x, y, 5) -- Bilder zeichnen end function ka.drawFlexPic6(x, y) drawFlexPic(x, y, 6) -- Bilder zeichnen end -- ---------------------------------- -- Zeichnet die Daten des Ozilloskops -- ---------------------------------- function ka.drawOszi(x, y) -- Oszilloskop -- local font = FONT_MINI local height = lcd.getTextHeight(FONT_MINI) local width local kooUrX, kooUrY -- Hintergrundfarbe einstellen changeColorByIndex(Oszi.Graph.BgCol, 255) if Oszi.Graph.BgCol ~= 0 then drawKaBackground(x + 2, y + 0, Oszi.Graph.Width, Oszi.Graph.Height) end setTextColorDependBG(43, 255, Oszi.Graph.BgCol) -- Koordinatenkreuz zeichnen ---------------------------- width = lcd.getTextWidth(font, Oszi.Graph.Legend.TextTime) -- Koordinatenkreuz zeichnen -- links lcd.drawLine(x + Oszi.Graph.AxisDistant, y + Oszi.Graph.AxisDistant - 3, x + Oszi.Graph.AxisDistant, y + Oszi.Graph.Height - Oszi.Graph.AxisDistant + 3 ) lcd.drawLine(x + Oszi.Graph.Width - Oszi.Graph.AxisDistant, y + Oszi.Graph.AxisDistant - 3, x + Oszi.Graph.Width - Oszi.Graph.AxisDistant, y + Oszi.Graph.Height - Oszi.Graph.AxisDistant + 3 ) -- Pfeil Y-Achse -- links lcd.drawLine(x + Oszi.Graph.AxisDistant, y + Oszi.Graph.AxisDistant - 3, x + Oszi.Graph.AxisDistant - Oszi.Graph.ArrowSize/2, y + Oszi.Graph.AxisDistant - 3 + Oszi.Graph.ArrowSize ) -- links lcd.drawLine(x + Oszi.Graph.AxisDistant, y + Oszi.Graph.AxisDistant - 3, x + Oszi.Graph.AxisDistant + Oszi.Graph.ArrowSize/2, y + Oszi.Graph.AxisDistant - 3 + Oszi.Graph.ArrowSize ) lcd.drawLine(x + Oszi.Graph.Width - Oszi.Graph.AxisDistant, y + Oszi.Graph.AxisDistant - 3, x + Oszi.Graph.Width - Oszi.Graph.AxisDistant - Oszi.Graph.ArrowSize/2, y + Oszi.Graph.AxisDistant - 3 + Oszi.Graph.ArrowSize ) lcd.drawLine(x + Oszi.Graph.Width - Oszi.Graph.AxisDistant, y + Oszi.Graph.AxisDistant - 3, x + Oszi.Graph.Width - Oszi.Graph.AxisDistant + Oszi.Graph.ArrowSize/2, y + Oszi.Graph.AxisDistant - 3 + Oszi.Graph.ArrowSize ) if Oszi.Graph.posXaxis == 3 then -- x-Achse unten lcd.drawLine(x + Oszi.Graph.AxisDistant - 3, y + Oszi.Graph.Height - Oszi.Graph.AxisDistant, x + Oszi.Graph.Width - 3, y + Oszi.Graph.Height - Oszi.Graph.AxisDistant) -- Pfeil X-Achse lcd.drawLine(x + Oszi.Graph.Width - Oszi.Graph.AxisDistant + 3, y + Oszi.Graph.Height - Oszi.Graph.AxisDistant, x + Oszi.Graph.Width - Oszi.Graph.AxisDistant + 3 - Oszi.Graph.ArrowSize, y + Oszi.Graph.Height - Oszi.Graph.AxisDistant - Oszi.Graph.ArrowSize/2 ) lcd.drawLine(x + Oszi.Graph.Width - Oszi.Graph.AxisDistant + 3, y + Oszi.Graph.Height - Oszi.Graph.AxisDistant, x + Oszi.Graph.Width - Oszi.Graph.AxisDistant + 3 - Oszi.Graph.ArrowSize, y + Oszi.Graph.Height - Oszi.Graph.AxisDistant + Oszi.Graph.ArrowSize/2 ) -- Beschriftung Zeitachse lcd.drawText(x + Oszi.Graph.Width - Oszi.Graph.Legend.xPosTx - width*2 + 2, y + Oszi.Graph.Height - Oszi.Graph.AxisDistant - height, Oszi.Graph.Legend.TextTime, font) -- Korrdinatenursprung Y-Wert kooUrY = y + Oszi.Graph.Height - Oszi.Graph.AxisDistant elseif Oszi.Graph.posXaxis == 2 then -- x-Achse mitte lcd.drawLine(x + Oszi.Graph.AxisDistant - 3, y + Oszi.Graph.Height / 2, x + Oszi.Graph.Width - 3, y + Oszi.Graph.Height / 2) -- Pfeil X-Achse lcd.drawLine(x + Oszi.Graph.Width - Oszi.Graph.AxisDistant + 3, y + Oszi.Graph.Height / 2, x + Oszi.Graph.Width - Oszi.Graph.AxisDistant + 3 - Oszi.Graph.ArrowSize, y + Oszi.Graph.Height / 2 - Oszi.Graph.ArrowSize/2 ) lcd.drawLine(x + Oszi.Graph.Width - Oszi.Graph.AxisDistant + 3, y + Oszi.Graph.Height / 2, x + Oszi.Graph.Width - Oszi.Graph.AxisDistant + 3 - Oszi.Graph.ArrowSize, y + Oszi.Graph.Height / 2 + Oszi.Graph.ArrowSize/2 ) -- Beschriftung Zeitachse lcd.drawText(x + Oszi.Graph.Width - Oszi.Graph.Legend.xPosTx - width*2 + 2, y + Oszi.Graph.Height/2, Oszi.Graph.Legend.TextTime, font) -- Korrdinatenursprung Y-Wert kooUrY = y + Oszi.Graph.Height / 2 else -- x-Achse oben lcd.drawLine(x + Oszi.Graph.AxisDistant - 3, y + Oszi.Graph.AxisDistant, x + Oszi.Graph.Width - 3, y + Oszi.Graph.AxisDistant) -- Pfeil X-Achse lcd.drawLine(x + Oszi.Graph.Width - Oszi.Graph.AxisDistant + 3, y + Oszi.Graph.AxisDistant, x + Oszi.Graph.Width - Oszi.Graph.AxisDistant + 3 - Oszi.Graph.ArrowSize, y + Oszi.Graph.AxisDistant - Oszi.Graph.ArrowSize/2 ) lcd.drawLine(x + Oszi.Graph.Width - Oszi.Graph.AxisDistant + 3, y + Oszi.Graph.AxisDistant, x + Oszi.Graph.Width - Oszi.Graph.AxisDistant + 3 - Oszi.Graph.ArrowSize, y + Oszi.Graph.AxisDistant + Oszi.Graph.ArrowSize/2 ) -- Beschriftung Zeitachse lcd.drawText(x + Oszi.Graph.Width - Oszi.Graph.Legend.xPosTx - width*2 + 2, y + Oszi.Graph.AxisDistant, Oszi.Graph.Legend.TextTime, font) -- Korrdinatenursprung Y-Wert kooUrY = y + Oszi.Graph.AxisDistant end -- Skala einzeichnen -------------------- local xStep = ( Oszi.Graph.Width - 2*Oszi.Graph.AxisDistant ) / 10 local yStep if Oszi.Graph.posXaxis == 2 then yStep = ( Oszi.Graph.Height - 2*Oszi.Graph.AxisDistant ) / 10 / 2 else yStep = ( Oszi.Graph.Height - 2*Oszi.Graph.AxisDistant ) / 10 end -- Gitter --------- if Oszi.Graph.Legend.Gitter then -- Zeichnen changeColorByIndex(40, 255) -- Hellgrau for i=1, 10 do -- Senkrechte Linien -- lcd.drawLine( x + Oszi.Graph.AxisDistant + i * xStep, y + Oszi.Graph.AxisDistant, -- links x + Oszi.Graph.AxisDistant + i * xStep, y - Oszi.Graph.AxisDistant + Oszi.Graph.Height) lcd.drawLine( x + Oszi.Graph.AxisDistant + (i-1) * xStep, y + Oszi.Graph.AxisDistant, x + Oszi.Graph.AxisDistant + (i-1) * xStep, y - Oszi.Graph.AxisDistant + Oszi.Graph.Height) -- Waagerechte Linien if i==5 or i==10 then if Oszi.Graph.posXaxis == 1 then lcd.drawLine( x + Oszi.Graph.AxisDistant, kooUrY + i * yStep, x - Oszi.Graph.AxisDistant + Oszi.Graph.Width, kooUrY + i * yStep ) elseif Oszi.Graph.posXaxis == 2 then lcd.drawLine( x + Oszi.Graph.AxisDistant, kooUrY + i * yStep, x - Oszi.Graph.AxisDistant + Oszi.Graph.Width, kooUrY + i * yStep ) lcd.drawLine( x + Oszi.Graph.AxisDistant, kooUrY - i * yStep, x - Oszi.Graph.AxisDistant + Oszi.Graph.Width, kooUrY - i * yStep ) else lcd.drawLine( x + Oszi.Graph.AxisDistant, kooUrY - i * yStep, x - Oszi.Graph.AxisDistant + Oszi.Graph.Width, kooUrY - i * yStep ) end end end changeColorByIndex(43, 255) -- Schwarz end -- Unterteilung und Beschriftung -------------------------------- --[[ links for i=1, 10 do local text = string.format("%d", (Oszi.Data.Values.maxTime/10*i/1000) ) local lenHalbe = lcd.getTextWidth(font, text) / 2 -- X-Achse if i==5 or i==10 then lcd.drawLine( x + Oszi.Graph.AxisDistant + i * xStep, kooUrY + 4, x + Oszi.Graph.AxisDistant + i * xStep, kooUrY - 4 ) if Oszi.Graph.posXaxis == 3 then lcd.drawText(x + Oszi.Graph.AxisDistant + i * xStep - lenHalbe, kooUrY - Oszi.Graph.AxisDistant - height, text, font) else lcd.drawText(x + Oszi.Graph.AxisDistant + i * xStep - lenHalbe, kooUrY + Oszi.Graph.AxisDistant, text, font) end elseif i==1 then lcd.drawLine( x + Oszi.Graph.AxisDistant + i * xStep, kooUrY + 4, x + Oszi.Graph.AxisDistant + i * xStep, kooUrY - 4 ) if Oszi.Graph.posXaxis == 3 then lcd.drawText(x + Oszi.Graph.AxisDistant + i * xStep - lenHalbe, kooUrY - Oszi.Graph.AxisDistant - height, text, font) else lcd.drawText(x + Oszi.Graph.AxisDistant + i * xStep - lenHalbe, kooUrY + Oszi.Graph.AxisDistant, text, font) end else lcd.drawLine( x + Oszi.Graph.AxisDistant + i * xStep, kooUrY + 2, x + Oszi.Graph.AxisDistant + i * xStep, kooUrY - 2 ) end --]] -- Y-Achse ist rechts for i=1, 10 do local text = string.format("-%d", (Oszi.Data.Values.maxTime/10*i/1000) ) local lenHalbe = lcd.getTextWidth(font, text) / 2 -- X-Achse if i==5 or i==10 then lcd.drawLine( x + Oszi.Graph.Width - Oszi.Graph.AxisDistant - i * xStep, kooUrY + 4, x + Oszi.Graph.Width - Oszi.Graph.AxisDistant - i * xStep, kooUrY - 4 ) if Oszi.Graph.posXaxis == 3 then lcd.drawText(x + Oszi.Graph.Width - Oszi.Graph.AxisDistant - i * xStep - lenHalbe +i/2, kooUrY - Oszi.Graph.AxisDistant - height, text, font) -- '+i/2' ist ein Offset, damit das - Zeichen links einigermaßen paßt. else lcd.drawText(x + Oszi.Graph.Width - Oszi.Graph.AxisDistant - i * xStep - lenHalbe +i/2, kooUrY + Oszi.Graph.AxisDistant, text, font) end elseif i==1 then lcd.drawLine( x + Oszi.Graph.Width - Oszi.Graph.AxisDistant - i * xStep, kooUrY + 4, x + Oszi.Graph.Width - Oszi.Graph.AxisDistant - i * xStep, kooUrY - 4 ) if Oszi.Graph.posXaxis == 3 then lcd.drawText(x + Oszi.Graph.Width - Oszi.Graph.AxisDistant - i * xStep - lenHalbe +i/2, kooUrY - Oszi.Graph.AxisDistant - height, text, font) else lcd.drawText(x + Oszi.Graph.Width - Oszi.Graph.AxisDistant - i * xStep - lenHalbe +i/2, kooUrY + Oszi.Graph.AxisDistant, text, font) end else lcd.drawLine( x + Oszi.Graph.Width - Oszi.Graph.AxisDistant - i * xStep, kooUrY + 2, x + Oszi.Graph.Width - Oszi.Graph.AxisDistant - i * xStep, kooUrY - 2 ) end -- Y-Achse text = string.format("%d%%", i*10) if i==5 or i==10 then --[[ links lcd.drawLine( x + Oszi.Graph.AxisDistant - 3, kooUrY + i * yStep, x + Oszi.Graph.AxisDistant + 3, kooUrY + i * yStep ) lcd.drawLine( x + Oszi.Graph.AxisDistant - 3, kooUrY - i * yStep, x + Oszi.Graph.AxisDistant + 3, kooUrY - i * yStep ) --]] lcd.drawLine( x + Oszi.Graph.Width - Oszi.Graph.AxisDistant - 3, kooUrY + i * yStep, x + Oszi.Graph.Width - Oszi.Graph.AxisDistant + 3, kooUrY + i * yStep ) lcd.drawLine( x + Oszi.Graph.Width - Oszi.Graph.AxisDistant - 3, kooUrY - i * yStep, x + Oszi.Graph.Width - Oszi.Graph.AxisDistant + 3, kooUrY - i * yStep ) if Oszi.Graph.posXaxis == 1 then -- links lcd.drawText(x + Oszi.Graph.AxisDistant * 2, kooUrY + i * yStep - height/2, "-"..text, font) lcd.drawText(x + Oszi.Graph.Width - Oszi.Graph.AxisDistant*2 - lcd.getTextWidth(font, text), kooUrY + i * yStep - height/2, "-"..text, font) elseif Oszi.Graph.posXaxis == 2 then -- links lcd.drawText(x + Oszi.Graph.AxisDistant * 2, kooUrY + i * yStep - height/2, "-"..text, font) -- links lcd.drawText(x + Oszi.Graph.AxisDistant * 2, kooUrY - i * yStep - height/2, text, font) lcd.drawText(x + Oszi.Graph.Width - Oszi.Graph.AxisDistant*2 - lcd.getTextWidth(font, text), kooUrY + i * yStep - height/2, "-"..text, font) lcd.drawText(x + Oszi.Graph.Width - Oszi.Graph.AxisDistant*2 - lcd.getTextWidth(font, text), kooUrY - i * yStep - height/2 +2, text, font) else -- links lcd.drawText(x + Oszi.Graph.AxisDistant * 2, kooUrY - i * yStep - height/2, text, font) lcd.drawText(x + Oszi.Graph.Width - Oszi.Graph.AxisDistant*2 - lcd.getTextWidth(font, text), kooUrY - i * yStep - height/2, text, font) end else --[[ links lcd.drawLine( x + Oszi.Graph.AxisDistant - 1, kooUrY + i * yStep, x + Oszi.Graph.AxisDistant + 1, kooUrY + i * yStep ) lcd.drawLine( x + Oszi.Graph.AxisDistant - 1, kooUrY - i * yStep, x + Oszi.Graph.AxisDistant + 1, kooUrY - i * yStep ) --]] lcd.drawLine( x + Oszi.Graph.Width - Oszi.Graph.AxisDistant - 1, kooUrY + i * yStep, x + Oszi.Graph.Width - Oszi.Graph.AxisDistant + 1, kooUrY + i * yStep ) lcd.drawLine( x + Oszi.Graph.Width - Oszi.Graph.AxisDistant - 1, kooUrY - i * yStep, x + Oszi.Graph.Width - Oszi.Graph.AxisDistant + 1, kooUrY - i * yStep ) end end -- Kurve zeichnen -- -------------- kooUrX = x + Oszi.Graph.AxisDistant --print("kooUrX="..kooUrX.." kooUrY="..kooUrY) --[[ Oszi.Data.Values.Ch1.TVpointer = nil -- Nummer des TeleValues, das darzustellen ist (1 - 24) Oszi.Data.Values.Ch1.maxValue = nil -- maximaler physikalischer Wert zur Normierung Oszi.Data.Values.Ch1.Header = nil -- Überschrift des Wertes zur Anzeige in der Legende Oszi.Data.Values.Ch1.Point = {} -- Wertespeicher Oszi.Data.Values.Ch1.Time = {} -- Zeitstempel --]] local i, j local Idx local accOfValues = Oszi.Data.Values.maxTime / Oszi.Data.Values.T local ov = Oszi.Data.Values local maxPixelsX = (Oszi.Graph.Width - 2 * Oszi.Graph.AxisDistant) / (Oszi.Data.Values.maxTime / Oszi.Data.Values.T) local maxPixelsY local FontHeight = lcd.getTextHeight(FONT_MINI) local xPosNamen = Oszi.Graph.Legend.xPosTx + 0 -- Pixelverschiebung wegen Skalenbeschriftung local yPosNamen = Oszi.Graph.Legend.yPosTx local KanalName = "" for j = 1, Oszi.Data.Values.AccOfChannels do Idx = string.format("Ch%d", j) if(ov[Idx].TVpointer ~= nil) then -- Dieser Kanal wird benutzt -- Kanalbeschreibung changeColorByIndex(ov[Idx].LnCol, 255) -- Namen des Kanals zusammensetzen KanalName = ov[Idx].Header.." ("..ov[Idx].maxValue..ov[Idx].Unit..")" lcd.drawText(x + xPosNamen, y + yPosNamen, KanalName, font) -- Nächste Textposition vorbereiten xPosNamen = xPosNamen + 10 + lcd.getTextWidth(font, KanalName) if j == 2 then -- Zweite Zeile setzen KanalName = "" -- Namen neu eintragen xPosNamen = Oszi.Graph.Legend.xPosTx + 0 -- Pixelverschiebung wegen Skalenbeschriftung yPosNamen = yPosNamen + FontHeight end -- Normierung für die Y-Achse maxPixelsY = (Oszi.Graph.Height - 2 * Oszi.Graph.AxisDistant) / ov[Idx].maxValue if Oszi.Graph.posXaxis == 2 then -- Es sollen positive und negative Werte angezeigt werden --> Y-Auflösung halbieren maxPixelsY = maxPixelsY / 2 end -- Linie zeichnen -- lcd.drawLine( kooUrX, kooUrY, -- kooUrX + maxPixelsX, kooUrY - ov[Idx].Point[1] * maxPixelsY ) for i = 1, accOfValues - 1 do lcd.drawLine( kooUrX + maxPixelsX * i, kooUrY - ov[Idx].Point[i] * maxPixelsY, kooUrX + maxPixelsX * (i+1),kooUrY - ov[Idx].Point[i+1] * maxPixelsY ) end end end -- Falls die Stoppschalter betätigt wurde, soll die Zeit eingetragen werden local stoppOszi = system.getInputsVal(sw.OsziStoppSw) local bStoppOszi = (not stoppOszi or stoppOszi > 0) and (sw.OsziStoppSw ~= nil) if bStoppOszi and not Oszi.Graph.Legend.bStoppWritten then local dt = system.getDateTime() Oszi.Data.Values.sStoppText = string.format("%s%02d.%02d.%d %02d:%02d:%02d", trans.menu_OsziControlStopTime, dt.day, dt.mon, dt.year, dt.hour, dt.min, dt.sec) Oszi.Graph.Legend.bStoppWritten = true end if not bStoppOszi and Oszi.Graph.Legend.bStoppWritten then Oszi.Graph.Legend.bStoppWritten = false Oszi.Data.Values.sStoppText = "" end if bStoppOszi or string.len(Oszi.Data.Values.sStoppText) > 0 then setTextColorDependBG(43, 255, Oszi.Graph.BgCol) lcd.drawText(x + Oszi.Graph.Width / 2, y + Oszi.Graph.Height - 2 * Oszi.Graph.AxisDistant - height, Oszi.Data.Values.sStoppText, font) end end function ka.drawTiles(index, startX) local list = positions[ index] if list ~= nil then --[[ local list = positions[ index] local startY = spacers [-index] local spaceY = spacers [ index] local value, method, space --]] -- local sIndex = string.format("-%0.f", math.floor(index + 0.5)) -- Integer-Absicherung (typisches LUA 5.3 Problem) local sIndex = string.format("%d", math.tointeger(index)) local negsIndex = "-"..sIndex local startY = spacers [negsIndex] local spaceY = spacers [sIndex] local value, method, space -- print(string.format("positions[%s]=%s startY=%s, spaceY=%s", index, positions[index], startY, spaceY )) for i=1, positionMax do value = list[i] --[[ -- Wichtig zur kontrolle if (not tile) then tile = 0 lastTile = 0 end if (index == 3 and i == 1) then local time = system.getTime() if (time - lastTile >= 1) then --3 geschwindigkeit lastTile = time tile = tile % methodsMax + 1 print(tiles and tiles[tile] or tile) end value = tile end --]] if(value > #methods) then -- Eine alte Kachel liegt vor value = 1 end if (value > 1) then method = methods[value] method(startX, startY) setTextColorDependBG(43, 255, 0) startY = startY + heights[value] if (heights[value] > 0) then startY = startY + spaceY end if (startY > heightMax) then break end end end end drawAlert(0, 0) drawBatteryAlert(0, 0) end local function deleteOldVariables() -- Diese Funktion löscht die alten Variablen, die mit pSave gespeichert wurden. -- Es wird ein 'nil' hineingeschrieben, was ein Entfernen der Variable im JSON-Feld zur Folge hat. local i, zeile, zeileShort for i=1, 6 do zeileShort = string.format("FP%d", i) system.pSave(zeileShort.."sw", nil) system.pSave(zeileShort.."name", nil) system.pSave(zeileShort.."head", nil) system.pSave(zeileShort.."fln1", nil) system.pSave(zeileShort.."img1", nil) system.pSave(zeileShort.."fln2", nil) system.pSave(zeileShort.."img2", nil) system.pSave(zeileShort.."fln3", nil) system.pSave(zeileShort.."img3", nil) system.pSave(zeileShort.."higt", nil) system.pSave(zeileShort.."bcol", nil) system.pSave(zeileShort.."horz", nil) system.pSave(zeileShort.."vert", nil) system.pSave(zeileShort.."lm12", nil) system.pSave(zeileShort.."lm23", nil) system.pSave(zeileShort.."lm32", nil) system.pSave(zeileShort.."lm21", nil) end -- Löschen der TeleValues ------------------------- for i = 1, 15 do zeileShort = string.format("TV%d", i) system.pSave(zeileShort.."name", nil) system.pSave(zeileShort.."head", nil) system.pSave(zeileShort.."horz", nil) system.pSave(zeileShort.."size", nil) system.pSave(zeileShort.."swTV", nil) system.pSave(zeileShort.."snid", nil) system.pSave(zeileShort.."snno", nil) system.pSave(zeileShort.."sidx", nil) system.pSave(zeileShort.."styp", nil) system.pSave(zeileShort.."para", nil) system.pSave(zeileShort.."pano", nil) system.pSave(zeileShort.."pidx", nil) system.pSave(zeileShort.."einh", nil) system.pSave(zeileShort.."korr", nil) system.pSave(zeileShort.."komm", nil) system.pSave(zeileShort.."hght", nil) system.pSave(zeileShort.."wdth", nil) system.pSave(zeileShort.."bcol", nil) system.pSave(zeileShort.."lim1", nil) system.pSave(zeileShort.."lim2", nil) system.pSave(zeileShort.."lim3", nil) system.pSave(zeileShort.."lim4", nil) system.pSave(zeileShort.."txt1", nil) system.pSave(zeileShort.."txt2", nil) system.pSave(zeileShort.."txt3", nil) system.pSave(zeileShort.."txt4", nil) system.pSave(zeileShort.."flsh", nil) end -- for system.pSave("filesave", fileSave) system.pSave("AKTAiAccOfStorage", SpecTiles.AkkuTank.iAccOfStorage) system.pSave("AKTAiSensorNo1", nil) system.pSave("AKTAsSensorName1", nil) system.pSave("AKTAiSensorId1", nil) system.pSave("AKTAiSensorType1", nil) system.pSave("AKTAiSensorValueNo1", nil) system.pSave("AKTAsSensorValueName1",nil) system.pSave("AKTAiSensorValueIdx1", nil) system.pSave("AKTAsSensorUnit1", nil) system.pSave("AKTAbGrowing1", nil) system.pSave("AKTAiCapacity1", nil) system.pSave("AKTAiWarningValue1", nil) system.pSave("AKTAiAlarmValue1", nil) system.pSave("AKTAsWarningSound1", nil) system.pSave("AKTAsAlarmSound1", nil) system.pSave("AKTAswValPlay1", nil) system.pSave("AKTAsRepresentUnit1", nil) system.pSave("AKTAsRepresentation1", nil) system.pSave("AKTAsKorrekturfaktor1",nil) system.pSave("AKTAbConvertGrowToShrk1", nil) system.pSave("AKTAiConvGtoScapacity1", nil) system.pSave("AKTAbShowScale", nil) system.pSave("AKTAiTilesHeigtht", nil) system.pSave("AKTAiBgColor", nil) system.pSave("AKTAiTrans", nil) system.pSave("AKTAbAnsageRestmenge", nil) system.pSave("AKTAsPicFileName", nil) system.pSave("AKTAiPicFileIndex", nil) system.pSave("AKTAiSensorNo2", nil) system.pSave("AKTAsSensorName2", nil) system.pSave("AKTAiSensorId2", nil) system.pSave("AKTAiSensorType2", nil) system.pSave("AKTAiSensorValueNo2", nil) system.pSave("AKTAsSensorValueName2",nil) system.pSave("AKTAiSensorValueIdx2", nil) system.pSave("AKTAsSensorUnit2", nil) system.pSave("AKTAbGrowing2", nil) system.pSave("AKTAiCapacity2", nil) system.pSave("AKTAiWarningValue2", nil) system.pSave("AKTAiAlarmValue2", nil) system.pSave("AKTAsWarningSound2", nil) system.pSave("AKTAsAlarmSound2", nil) system.pSave("AKTAswValPlay2", nil) system.pSave("AKTAsRepresentation2", nil) system.pSave("AKTAsRepresentUnit2", nil) system.pSave("AKTAsKorrekturfaktor2",nil) system.pSave("AKTAbConvertGrowToShrk2", nil) system.pSave("AKTAiConvGtoScapacity2", nil) system.pSave("BeepCmdFile", nil) system.pSave("BeepCmdFileIdx", nil) system.pSave("MTAGsSensorName", nil) system.pSave("MTAGiSensorNo", nil) system.pSave("MTAGiSensorID", nil) system.pSave("MTAGiSensorIdx", nil) system.pSave("MTAGiSensorType", nil) system.pSave("MTAGiBgColor", nil) system.pSave("GPSsSensorName", nil) system.pSave("GPSiSensorNo", nil) system.pSave("GPSiSensorID", nil) system.pSave("GPSiSensorIdx", nil) system.pSave("GPSiSensorType", nil) system.pSave("GPSsLatParam", nil) system.pSave("GPSiLatParamNo", nil) system.pSave("GPSiLatParamIdx", nil) system.pSave("GPSsLatEinheit", nil) system.pSave("GPSiLatNachkomma", nil) system.pSave("GPSsLonParam", nil) system.pSave("GPSiLonParamNo", nil) system.pSave("GPSiLonParamIdx", nil) system.pSave("GPSsLonEinheit", nil) system.pSave("GPSiLonNachkomma", nil) system.pSave("GPSiBgColor", nil) system.pSave("ViSsSensorNameA", nil) system.pSave("ViSiSensorNoA", nil) system.pSave("ViSiSensorIDA", nil) system.pSave("ViSiSensorIdxA", nil) system.pSave("ViSiSensorTypeA", nil) system.pSave("ViSsParamA", nil) system.pSave("ViSiParamNoA", nil) system.pSave("ViSiParamIdxA", nil) system.pSave("ViSsEinheitA", nil) system.pSave("ViSiNachkommaA", nil) system.pSave("ViSsSensorNameB", nil) system.pSave("ViSiSensorNoB", nil) system.pSave("ViSiSensorIDB", nil) system.pSave("ViSiSensorIdxB", nil) system.pSave("ViSiSensorTypeB", nil) system.pSave("ViSsParamB", nil) system.pSave("ViSiParamNoB", nil) system.pSave("ViSiParamIdxB", nil) system.pSave("ViSsEinheitB", nil) system.pSave("ViSiNachkommaB", nil) system.pSave("ViSiOperation", nil) system.pSave("ViSunit", nil) system.pSave("NoAnsageHoeheMeter", nil) system.pSave("NoAnsageMotorStrom", nil) system.pSave("VorsSensorName", nil) system.pSave("VoriSensorNo", nil) system.pSave("VoriSensorID", nil) system.pSave("VoriSensorIdx", nil) system.pSave("VoriSensorType", nil) system.pSave("VorsParam", nil) system.pSave("VoriParamNo", nil) system.pSave("VoriParamIdx", nil) system.pSave("VorsEinheit", nil) system.pSave("VoriNachkomma", nil) end local function loadConfig(filename) if (filename:len() > 0) then local newValue = 1 local file = io.open(filename, "r") if not file then return end -- Datei konnte nicht geöffnet werden, vorzeitig beenden if (file) then local line, index, value,version line = io.readline(file, true) version = line:match("%[([%w%.]+)%]") --print(version) if version ~= "7.0.8h" then system.messageBox(trans.Msg_IncompatibleVersion .. " " .. version, 5) io.close(file) -- Falsche Version, beenden return end if (not version) then io.seek(file, "set") end for i=1, positionsMax do if (not version and i > 6) then line = "1 1 1 1 1 1" else line = io.readline(file, true) end index = 0 if (line) then for value in line:gmatch("%d+") do index = index + 1 value = tonumber(value) positions[i][index] = value end end for j=index+1, positionMax do positions[i][j] = 1 end end -- Read params for i=1, paramsMax do line = io.readline(file, true) index = 1 if (line) then for value in line:gmatch("%d+") do index = index + 1 value = tonumber(value) params[i][index] = value end end for j=index+1, sensorsMax do params[i][j] = 0 end end line = io.readline(file, true) index = 0 if (line) then for value in line:gmatch("%d+") do index = -index if (index <= 0) then index = index - 1 end value = tonumber(value) spacers[index] = value end end for i=1, positionsMax do if (not spacers[-i]) then spacers[-i] = 3 end if (not spacers[i]) then spacers[i] = 1 end end --IG Read Switches local SwitchState = {} local sCmp = "---" line = io.readline(file, true) if(line and (string.find(line,sCmp) == nil)) then SwitchState = json.decode(line) sw.startBeepTimerSw = system.createSwitch(SwitchState[1], SwitchState[2], SwitchState[3]) end line = io.readline(file, true) if(line and (string.find(line,sCmp) == nil)) then SwitchState = json.decode(line) sw.pauseBeepTimerSw = system.createSwitch(SwitchState[1], SwitchState[2], SwitchState[3]) end line = io.readline(file, true) if(line and (string.find(line,sCmp) == nil)) then SwitchState = json.decode(line) sw.an3Sw = system.createSwitch(SwitchState[1], SwitchState[2], SwitchState[3]) end line = io.readline(file, true) if(line and (string.find(line,sCmp) == nil)) then SwitchState = json.decode(line) sw.an4Sw = system.createSwitch(SwitchState[1], SwitchState[2], SwitchState[3]) end line = io.readline(file, true) if(line and (string.find(line,sCmp) == nil)) then SwitchState = json.decode(line) sw.capaSw = system.createSwitch(SwitchState[1], SwitchState[2], SwitchState[3]) end line = io.readline(file, true) if(line and (string.find(line,sCmp) == nil)) then SwitchState = json.decode(line) sw.speedSw = system.createSwitch(SwitchState[1], SwitchState[2], SwitchState[3]) end line = io.readline(file, true) if(line and (string.find(line,sCmp) == nil)) then SwitchState = json.decode(line) sw.engineSw = system.createSwitch(SwitchState[1], SwitchState[2], SwitchState[3]) end line = io.readline(file, true) if(line and (string.find(line,sCmp) == nil)) then SwitchState = json.decode(line) sw.assSw = system.createSwitch(SwitchState[1], SwitchState[2], SwitchState[3]) end line = io.readline(file, true) if(line and (string.find(line,sCmp) == nil)) then SwitchState = json.decode(line) sw.flightSw = system.createSwitch(SwitchState[1], SwitchState[2], SwitchState[3]) end line = io.readline(file, true) if(line and (string.find(line,sCmp) == nil)) then SwitchState = json.decode(line) sw.startCountdownTimerSw = system.createSwitch(SwitchState[1], SwitchState[2], SwitchState[3]) end line = io.readline(file, true) if(line and (string.find(line,sCmp) == nil)) then SwitchState = json.decode(line) sw.pauseFlightTimerSw = system.createSwitch(SwitchState[1], SwitchState[2], SwitchState[3]) end line = io.readline(file, true) if(line and (string.find(line,sCmp) == nil)) then SwitchState = json.decode(line) sw.varihoheSw = system.createSwitch(SwitchState[1], SwitchState[2], SwitchState[3]) end line = io.readline(file, true) if(line and (string.find(line,sCmp) == nil)) then SwitchState = json.decode(line) sw.maxSw = system.createSwitch(SwitchState[1], SwitchState[2], SwitchState[3]) end line = io.readline(file, true) if(line and (string.find(line,sCmp) == nil)) then SwitchState = json.decode(line) sw.minSw = system.createSwitch(SwitchState[1], SwitchState[2], SwitchState[3]) end line = io.readline(file, true) if(line and (string.find(line,sCmp) == nil)) then SwitchState = json.decode(line) sw.statsTimeSw = system.createSwitch(SwitchState[1], SwitchState[2], SwitchState[3]) end line = io.readline(file, true) if(line and (string.find(line,sCmp) == nil)) then SwitchState = json.decode(line) sw.statsFlightSw = system.createSwitch(SwitchState[1], SwitchState[2], SwitchState[3]) end line = io.readline(file, true) if(line and (string.find(line,sCmp) == nil)) then SwitchState = json.decode(line) sw.resetBeepTimerSw = system.createSwitch(SwitchState[1], SwitchState[2], SwitchState[3]) end line = io.readline(file, true) if(line and (string.find(line,sCmp) == nil)) then SwitchState = json.decode(line) sw.resetRxSw = system.createSwitch(SwitchState[1], SwitchState[2], SwitchState[3]) end line = io.readline(file, true) if(line and (string.find(line,sCmp) == nil)) then SwitchState = json.decode(line) sw.resetTeleSw = system.createSwitch(SwitchState[1], SwitchState[2], SwitchState[3]) end line = io.readline(file, true) if(line and (string.find(line,sCmp) == nil)) then SwitchState = json.decode(line) sw.resetStatsSw = system.createSwitch(SwitchState[1], SwitchState[2], SwitchState[3]) end line = io.readline(file, true) if(line and (string.find(line,sCmp) == nil)) then SwitchState = json.decode(line) sw.resetmimaSw = system.createSwitch(SwitchState[1], SwitchState[2], SwitchState[3]) end line = io.readline(file, true) if(line and (string.find(line,sCmp) == nil)) then SwitchState = json.decode(line) sw.startFlightTimerSw = system.createSwitch(SwitchState[1], SwitchState[2], SwitchState[3]) end line = io.readline(file, true) line = io.readline(file, true) line = io.readline(file, true) if(line and (string.find(line,sCmp) == nil)) then SwitchState = json.decode(line) sw.SnapShotSw = system.createSwitch(SwitchState[1], SwitchState[2], SwitchState[3]) end line = io.readline(file, true) line = io.readline(file, true) line = io.readline(file, true) if(line and line ~= "") then variables.Collect.framed = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.Collect.textInverse = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then se.flightsReset = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then se.TimeDelay = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then se.vorflugvolt = json.decode(line) end line = io.readline(file, true) line = io.readline(file, true) line = io.readline(file, true) line = io.readline(file, true) line = io.readline(file, true) line = io.readline(file, true) line = io.readline(file, true) line = io.readline(file, true) line = io.readline(file, true) if(line and line ~= "") then se.nickname = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then se.again1 = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then se.again2 = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.Collect.flightsTotal = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.Collect.flightsToday = json.decode(line) end local iAccOfFlexPics = 2 line = io.readline(file, true) if(line and line ~= "") then iAccOfFlexPics = line end local zeile, zeileShort, text, text2, iPos1, iPos2 for i=1, iAccOfFlexPics do zeile = string.format("iFlexPicIdx%d", i) zeileShort = string.format("FP%d", i) line = io.readline(file, true) if(line and (string.find(line,sCmp) == nil)) then SwitchState = json.decode(line) FlexPics[zeile]["swFlexPic"] = system.createSwitch(SwitchState[1], SwitchState[2], SwitchState[3]) end line = io.readline(file, true) if(line and line ~= "") then FlexPics[zeile]["sFlexPicName"] = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then FlexPics[zeile]["sFlexPicHeader"] = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then FlexPics[zeile]["sFlexPicFileName1"] = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then FlexPics[zeile]["iFlexPicFileIndex1"] = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then FlexPics[zeile]["sFlexPicFileName2"] = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then FlexPics[zeile]["iFlexPicFileIndex2"] = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then FlexPics[zeile]["sFlexPicFileName3"] = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then FlexPics[zeile]["iFlexPicFileIndex3"] = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then FlexPics[zeile]["iFlexPicHeight"] = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then FlexPics[zeile]["iFlexPicBgColor"] = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then FlexPics[zeile]["iFlexPicAllignmentHorizontal"] = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then FlexPics[zeile]["iFlexPicAllignmentVertikal"] = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then FlexPics[zeile]["fFlexPicLim12"] = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then FlexPics[zeile]["fFlexPicLim23"] = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then FlexPics[zeile]["fFlexPicLim32"] = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then FlexPics[zeile]["fFlexPicLim21"] = json.decode(line) end end line = io.readline(file, true) --"End of Part ONE" -- +++++ Die TelVal-Daten laden +++++ line = io.readline(file, true) -- derzeit Reservezeile, es steht der Wert 'TelVal.iAccOfTelVal' = 15 in der Zeile for i=1, 15 do zeile = string.format("iTVInst%d", i) zeileShort = string.format("TV%d", i) line = io.readline(file, true) if(line and line ~= "") then TelVal[zeile].sTelValName = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then TelVal[zeile].sTelValHeader = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then TelVal[zeile].iTelValAllignmentHorizontal = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then TelVal[zeile].iTelValSize = json.decode(line) end line = io.readline(file, true) if(line and (string.find(line,sCmp) == nil)) then SwitchState = json.decode(line) TelVal[zeile].swTelVal = system.createSwitch(SwitchState[1], SwitchState[2], SwitchState[3]) end line = io.readline(file, true) if(line and line ~= "") then TelVal[zeile].sTelValSensor = json.decode(line) end -- Laden als Text, muß wieder in Zahl umgesetzt werden line = io.readline(file, true) if(line and line ~= "") then sensorIDtext = json.decode(line) TelVal[zeile].iTelValSensorID = tonumber(sensorIDtext) end line = io.readline(file, true) if(line and line ~= "") then TelVal[zeile].iTelValSensorNo = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then TelVal[zeile].iTelValSensorIdx = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then TelVal[zeile].iTelValSensorType = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then TelVal[zeile].sTelValParam = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then TelVal[zeile].iTelValParamNo = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then TelVal[zeile].iTelValParamIdx = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then TelVal[zeile].sTelValEinheit = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then text = json.decode(line) if(text ~= "---") then TelVal[zeile].fLimGrowWarning = tonumber(text) else TelVal[zeile].fLimGrowWarning = nil end end line = io.readline(file, true) if(line and line ~= "") then text = json.decode(line) if(text ~= "---") then TelVal[zeile].fLimGrowAlarm = tonumber(text) else TelVal[zeile].fLimGrowAlarm = nil end end line = io.readline(file, true) if(line and line ~= "") then text = json.decode(line) if(text ~= "---") then TelVal[zeile].fLimShrkWarning = tonumber(text) else TelVal[zeile].fLimShrkWarning = nil end end line = io.readline(file, true) if(line and line ~= "") then text = json.decode(line) if(text ~= "---") then TelVal[zeile].fLimShrkAlarm = tonumber(text) else TelVal[zeile].fLimShrkAlarm = nil end end line = io.readline(file, true) if(line and line ~= "") then TelVal[zeile].iLimBlinkenFreqZael = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then TelVal[zeile]["fTelValKorrekturfaktor"] = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then TelVal[zeile]["iTelValNachkomma"] = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then TelVal[zeile]["fTelValAct"] = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then TelVal[zeile]["fTelValMin"] = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then TelVal[zeile]["fTelValMax"] = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then TelVal[zeile]["iTelValHeight"] = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then TelVal[zeile]["iTelValWidth"] = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then TelVal[zeile]["iTelValBgColor"] = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then text = json.decode(line) if(text ~= "---") then TelVal[zeile].fTVTxLim1 = tonumber(text) else TelVal[zeile].fTVTxLim1 = nil end end line = io.readline(file, true) if(line and line ~= "") then text = json.decode(line) if(text ~= "---") then TelVal[zeile].fTVTxLim2 = tonumber(text) else TelVal[zeile].fTVTxLim2 = nil end end line = io.readline(file, true) if(line and line ~= "") then text = json.decode(line) if(text ~= "---") then TelVal[zeile].fTVTxLim3 = tonumber(text) else TelVal[zeile].fTVTxLim3 = nil end end line = io.readline(file, true) if(line and line ~= "") then text = json.decode(line) if(text ~= "---") then TelVal[zeile].fTVTxLim4 = tonumber(text) else TelVal[zeile].fTVTxLim4 = nil end end line = io.readline(file, true) if(line and line ~= "") then TelVal[zeile].sTVTxText1 = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then TelVal[zeile].sTVTxText2 = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then TelVal[zeile].sTVTxText3 = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then TelVal[zeile].sTVTxText4 = json.decode(line) end end line = io.readline(file, true) if(line and line ~= "") then fileSave = json.decode(line) end -- Laden der Spezial-Kachel-Daten Balkenanzeige line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.iAccOfStorage = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.iSensorNo1 = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.sSensorName1 = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then local sensorID1text = "" sensorID1text = json.decode(line) SpecTiles.AkkuTank.iSensorId1 = tonumber(sensorID1text) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.iSensorType1 = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.iSensorValueNo1 = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.sSensorValueName1 = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.iSensorValueIdx1 = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.sSensorUnit1 = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.iSensorNo2 = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.sSensorName2 = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then local sensorID2text = "" sensorID2text = json.decode(line) SpecTiles.AkkuTank.iSensorId2 = tonumber(sensorID2text) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.iSensorType2 = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.iSensorValueNo2 = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.sSensorValueName2 = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.iSensorValueIdx2 = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.sSensorUnit2 = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.bShowScale = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.iTilesHeigtht = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.iBgColor = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.bGrowing1 = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.bGrowing2 = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.iCapacity1 = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.iCapacity2 = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.iWarningValue1 = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.iAlarmValue1 = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.iWarningValue2 = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.iAlarmValue2 = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.sWarningSound1 = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.sAlarmSound1 = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.sWarningSound2 = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.sAlarmSound2 = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.bAnsageRestmenge = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.sPicFileName = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.iPicFileIndex = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.sRepresentation1 = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.sRepresentUnit1 = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.sRepresentation2 = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.sRepresentUnit2 = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.fKorrekturfaktor1 = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.fKorrekturfaktor2 = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.bConvertGrowToShrk1 = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.bConvertGrowToShrk2 = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.iTransparenz = json.decode(line) end line = io.readline(file, true) if(line and (string.find(line,sCmp) == nil)) then SwitchState = json.decode(line) SpecTiles.AkkuTank.swValPlay1 = system.createSwitch(SwitchState[1], SwitchState[2], SwitchState[3]) end line = io.readline(file, true) if(line and (string.find(line,sCmp) == nil)) then SwitchState = json.decode(line) SpecTiles.AkkuTank.swValPlay2 = system.createSwitch(SwitchState[1], SwitchState[2], SwitchState[3]) end line = io.readline(file, true) if(line and line ~= "") then variables.BeepCmd.File = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.BeepCmd.iFileListIdx = json.decode(line) end -- Und gleich laden if (variables.BeepCmd.File ~= "...") then local file = io.readall(folder..variables.BeepCmd.File..extensionJsonFile) variables.Sensors[variables.TimerBeepIdx].TimerBeepCmd = json.decode(file) else variables.Sensors[variables.TimerBeepIdx].TimerBeepCmd = nil end local sensorIDtext = "" -- MTAG Daten laden line = io.readline(file, true) if(line and line ~= "") then variables.MTAG.sSensorName = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then sensorIDtext = json.decode(line) variables.MTAG.iSensorID = tonumber(sensorIDtext) end line = io.readline(file, true) if(line and line ~= "") then variables.MTAG.iSensorNo = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.MTAG.iSensorIdx = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.MTAG.iSensorType = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.MTAG.iBgColor = json.decode(line) end -- GPS Daten laden line = io.readline(file, true) if(line and line ~= "") then variables.GPS.sSensorName = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then sensorIDtext = json.decode(line) variables.GPS.iSensorID = tonumber(sensorIDtext) end line = io.readline(file, true) if(line and line ~= "") then variables.GPS.iSensorNo = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.GPS.iSensorIdx = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.GPS.iSensorType = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.GPS.sLatParam = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.GPS.iLatParamNo = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.GPS.iLatParamIdx = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.GPS.sLatEinheit = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.GPS.iLatNachkomma = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.GPS.sLonParam = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.GPS.iLonParamNo = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.GPS.iLonParamIdx = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.GPS.sLonEinheit = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.GPS.iLonNachkomma = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.GPS.iBgColor = json.decode(line) end -- Virtuellen Sensor laden line = io.readline(file, true) if(line and line ~= "") then variables.ViS.sSensorNameA = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.ViS.iSensorNoA = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.ViS.iSensorIDA = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.ViS.iSensorIdxA = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.ViS.iSensorTypeA = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.ViS.sParamA = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.ViS.iParamNoA = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.ViS.iParamIdxA = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.ViS.sEinheitA = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.ViS.iNachkommaA = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.ViS.sSensorNameB = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.ViS.iSensorNoB = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.ViS.iSensorIDB = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.ViS.iSensorIdxB = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.ViS.iSensorTypeB = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.ViS.sParamB = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.ViS.iParamNoB = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.ViS.iParamIdxB = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.ViS.sEinheitB = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.ViS.iNachkommaB = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.ViS.iOperation = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.ViS.unit = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.Ans.iValueNoAnsageHoeheMeter = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.Ans.iValueNoAnsageHoeheMotorStrom = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.iConvGtoScapacity1 = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then SpecTiles.AkkuTank.iConvGtoScapacity2 = json.decode(line) end -- Vorflug Sensor laden line = io.readline(file, true) if(line and line ~= "") then variables.Vor.sSensorName = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.Vor.iSensorNo = json.decode(line) end -- Laden als Text, muß wieder in Zahl umgesetzt werden line = io.readline(file, true) if(line and line ~= "") then sensorIDtext = json.decode(line) variables.Vor.iSensorID = tonumber(sensorIDtext) end line = io.readline(file, true) if(line and line ~= "") then variables.Vor.iSensorIdx = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.Vor.iSensorType = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.Vor.sParam = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.Vor.iParamNo = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.Vor.iParamIdx = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.Vor.sEinheit = json.decode(line) end line = io.readline(file, true) if(line and line ~= "") then variables.Vor.iNachkomma = json.decode(line) end io.close(file) UpdateHeights() variables.Sensors[variables.CountdownTimeIdx].valSec = timeHMS.cSec variables.Sensors[variables.CountdownTimeIdx].valMin = timeHMS.cMin variables.Sensors[variables.FightsIdx].valTotal = variables.Collect.flightsTotal variables.Sensors[variables.FightsIdx].valToday = variables.Collect.flightsToday variables.Sensors[variables.TimerBeepIdx].valSec = timeHMS.bSec variables.Sensors[variables.TimerBeepIdx].valMin = timeHMS.bMin variables.BeepCmd.iState = -1 -- Command Datei laden if (variables.BeepCmd.File ~= "...") then local file = io.readall(folder..variables.BeepCmd.File..extensionJsonFile) variables.Sensors[variables.TimerBeepIdx].TimerBeepCmd = json.decode(file) end timeVars.bTime = nil timeVars.eTime = nil -- [[ -- Überflüssige Variablen löschen if se.gpstime ~= nil then se.gpstime = nil end if se.alarmValue2 ~= nil then se.alarmValue2 = nil end if se.alarmValue22 ~= nil then se.alarmValue22 = nil end if se.batteries ~= nil then se.batteries = nil end if se.gpsLatVal ~= nil then se.gpsLatVal = nil end if se.gpsLatDec ~= nil then se.gpsLatDec = nil end if se.gpsLonVal ~= nil then se.gpsLonVal = nil end if se.gpsLonDec ~= nil then se.gpsLonDec = nil end if se.speedSensor ~= nil then se.speedSensor = nil end if se.speedTime ~= nil then se.speedTime = nil end if se.alarmVoice2 ~= nil then se.alarmVoice2 = nil end if se.servo ~= nil then se.servo = nil end --]] --[[ -- se.alarmValue2 = 30 -- se.alarmValue22 = 50 -- se.batteries = 0 -- se.gpsLatVal = 0 -- se.gpsLatDec = 0 -- se.gpsLonVal = 0 -- se.gpsLonDec = 0 -- se.speedSensor = 1 -- se.speedTime = 3 -- se.alarmVoice2 = "" -- se.servo = 1 --]] se.option = 1 se.telwindows = 1 se.datens = 1 end end variables.Collect.flightsTotal = se.flightsReset variables.Collect.flightsToday = 0 -- Überflüssige Variablen löschen if se.gpstime ~= nil then se.gpstime = nil end if se.alarmValue2 ~= nil then se.alarmValue2 = nil end if se.alarmValue22 ~= nil then se.alarmValue22 = nil end if se.alarmValue1 ~= nil then se.alarmValue1 = nil end if se.alarmValue11 ~= nil then se.alarmValue11 = nil end if se.batteries ~= nil then se.batteries = nil end if se.gpsLatVal ~= nil then se.gpsLatVal = nil end if se.gpsLatDec ~= nil then se.gpsLatDec = nil end if se.gpsLonVal ~= nil then se.gpsLonVal = nil end if se.gpsLonDec ~= nil then se.gpsLonDec = nil end if se.speedSensor ~= nil then se.speedSensor = nil end if se.speedTime ~= nil then se.speedTime = nil end if se.alarmVoice2 ~= nil then se.alarmVoice2 = nil end if se.servo ~= nil then se.servo = nil end end local function updateTeleValueForm() TelVal.iActTelValProj = variables.iActShownTeleValue form.reinit(1) end local function updateFlexPicForm() FlexPics.iActFlexPicProj = variables.iActShownFlexPic form.reinit(1) end --Initialisiert Forms --------------------- local function initForm1(formID) local setTitle, addSpacer, addRow, addLabel = form.setTitle, form.addSpacer, form.addRow, form.addLabel local addIntbox, addSelectbox, addInputbox = form.addIntbox, form.addSelectbox, form.addInputbox local addCheckbox, addAudioFilebox, addTextbox = form.addCheckbox, form.addAudioFilebox, form.addTextbox local i -- Schleifenvariable local bSensorListeReset = false local text local index local ID setFiles() setImages() setTitle(trans.title1) addRow(2) addLabel({label=trans.option, font=FONT_BOLD}) addSelectbox(options, se.option, true, function(value) se.option = value form.reinit(1) end) changeColorByIndex(44, 255) bShowColorByPrintForm = false -- Keinen Farbbalken anzeigen ------------------------- addSpacer(318, 4) ------------------------- if (se.option == 1) then --Grundeinstllungen --Framed addRow(2) addLabel({label=trans.framed, width=275}) local framedForm framedForm = addCheckbox(variables.Collect.framed, function(value) variables.Collect.framed = not value form.setValue(framedForm, variables.Collect.framed) end) --Invers addRow(2) addLabel({label=trans.textInverse, width=275}) local textInverseForm textInverseForm = addCheckbox(variables.Collect.textInverse, function(value) variables.Collect.textInverse = not value form.setValue(textInverseForm, variables.Collect.textInverse) end) --Pilotenname ausblenden local nicknameForm addRow(2) addLabel({label=trans.nickname, width=275}) nicknameForm = addCheckbox(se.nickname, function(value) se.nickname = not value system.pSave("showPilotName", se.nickname and 1 or 0) form.setValue(nicknameForm, se.nickname) end) --Schnappschuß auslösen addRow(2) addLabel({label=trans.menu_Snapshot, width=230}) addInputbox(sw.SnapShotSw, true, function(value) if (not isSwitch(value)) then value = nil end sw.SnapShotSw = value end) --Speichern / Laden addSpacer(318, 10) addLabel({label=trans.saveLoad, font=FONT_BOLD}) -- Speichern addRow(2) addLabel({label=trans.save, width=125}) text = metaData.DataStorage.fileForSave text = string.sub(text, 6, text:len()-4) -- Einzugebenden Text separieren. addTextbox(text, 63, function(value) -- Dateinamen wieder zusammensetzen metaData.DataStorage.fileForSave = "DApp_"..value..extensionJsonFile form.setButton(4, "S", metaData.DataStorage.fileForSave:len() > 0 and ENABLED or DISABLED) end) -- Laden index = setJsnFilesLoadList(metaData.DataStorage.fileForLoad) addRow(2) addLabel({label=trans.load, width=125}) addSelectbox(variables.fileLoadList, index, true, function(value) text = value > 1 and variables.fileLoadList[value] or "" metaData.DataStorage.fileForLoad = "DApp_"..text..extensionJsonFile form.setButton(5, "L", metaData.DataStorage.fileForLoad:len() > 0 and ENABLED or DISABLED) end) --Copyright addRow(1) addLabel({label=metaData.AppName.." V"..metaData.Version.." "..metaData.AuthorsShort, font=FONT_MINI, alignRight=true}) elseif (se.option == 2) then -- Projektierung TeleValues local iAccOfTelVal = ACC_OF_TELEVALUES -- derzeit maximale Anzahl der TelVals, diese Variable sollte eigentlich Global sein. Würde 200 überschreiten. if (TelVal.iActTelValProj == nil) then TelVal.iActTelValProj = 1 end local zeile = string.format("iTVInst%d", TelVal.iActTelValProj) bShowColorByPrintForm = true changeColorByIndex(TelVal[zeile].iTelValBgColor, 255) addRow(3) text = string.format("%s %.0f", trans.menu_TelValNums, iAccOfTelVal) addLabel({label=text, width=200}) addIntbox(variables.iActShownTeleValue, 1, ACC_OF_TELEVALUES, TelVal.iActTelValProj, 0, 1, function(value) variables.iActShownTeleValue = value end, {width=40}) form.addLink( updateTeleValueForm, {label="v", alignRight=true, width=30}) -- Welche TelVal-Instanz soll nun projektiert werden? addRow(2) text = string.format("%s %.0f", trans.menu_TelValName, TelVal[zeile].iTelValNo) addLabel({label=text, width=180}) addTextbox(TelVal[zeile].sTelValName, 63, function(value) TelVal[zeile].sTelValName = value end) -- Sensoren / Geber auswählen addSpacer(318, 10) addLabel({label=trans.menu_TelValSensHeader, font=FONT_BOLD}) -- Sensor auswählen addRow(2) addLabel({label=trans.menu_TelValSensor, width=150}) addSelectbox(TelVal.SensorListLabel, TelVal[zeile].iTelValSensorNo, true, function(value) -- Den ausgewählten Sensor der Kachel zuordnen TelVal[zeile].sTelValSensor = TelVal.SensorListLabel[value] TelVal[zeile].iTelValSensorID = TelVal.SensorListId[value] TelVal[zeile].iTelValSensorNo = value TelVal[zeile].iTelValSensorIdx = TelVal.SensorListIdx[value] TelVal[zeile].iTelValSensorType = TelVal.SensorListType[value] -- Jetzt werden die derzeit noch eingestellten Sensorwerte zurückgesetzt TelVal[zeile].sTelValHeader = "?" TelVal[zeile].sTelValParam = "..." TelVal[zeile].iTelValParamNo = 1 TelVal[zeile].iTelValParamIdx = 1 TelVal[zeile].sTelValEinheit = " ?" TelVal[zeile].iTelValNachkomma = 1 TelVal[zeile].fTelValAct = 0.0 TelVal[zeile].fTelValMin = 0.0 TelVal[zeile].fTelValMax = 0.0 -- Ein eingestellter Geber wird nun auch zurückgesetzt TelVal[zeile].swTelVal = nil form.reinit(1) -- Die neu gewählte Sensorwerteliste auch richtig anzeigen end) -- Sensorwert zuordnen addRow(2) addLabel({label=trans.menu_TelValParameter, width=150}) -- Sicherheitsabfrage if(TelVal[zeile].iTelValSensorNo <= 1)then TelVal[zeile].iTelValSensorNo = 2 -- muß mindestens 1 sein -> kein Sensor angewählt bSensorListeReset = true else bSensorListeReset = false end -- Hier wird die Parameterliste des ausgewählten Sensors eingestellt local ParameterList, ParameterListIdx ParameterList = string.format("SensorListWertLabel%d", TelVal[zeile].iTelValSensorNo -1 ) -- Der erste Wert ist der NULL-Wert ParameterListIdx = string.format("SensorListWertLabelIdx%d", TelVal[zeile].iTelValSensorNo -1 ) -- Der erste Wert ist der NULL-Wert -- Den Offset durch den Sensor selbst berücksichtigen addSelectbox( TelVal[ParameterList], TelVal[zeile]["iTelValParamNo"], true, function(value) if (value == 1) then -- Sensorwert-Parameter zurücksetzen TelVal[zeile].sTelValHeader = "?" TelVal[zeile].sTelValParam = "..." TelVal[zeile].iTelValParamNo = 1 TelVal[zeile].iTelValParamIdx = 1 TelVal[zeile].sTelValEinheit = " ?" TelVal[zeile].iTelValNachkomma = 1 TelVal[zeile].fTelValAct = 0.0 TelVal[zeile].fTelValMin = 0.0 TelVal[zeile].fTelValMax = 0.0 else -- Den ausgewählten Sensorwert der TelVal-Instanz zuordnen TelVal[zeile].sTelValParam = TelVal[ParameterList][value] TelVal[zeile].iTelValParamIdx = TelVal[ParameterListIdx][value] TelVal[zeile].iTelValParamNo = value if (TelVal[zeile].iTelValSensorType == 2) then -- Interner / Sender Sensor TelVal[zeile].sTelValHeader = variables.Sensors[TelVal[zeile].iTelValParamIdx].label TelVal[zeile].sTelValEinheit = variables.Sensors[TelVal[zeile].iTelValParamIdx].unit TelVal[zeile].iTelValNachkomma = variables.Sensors[TelVal[zeile].iTelValParamIdx].decimals else -- Externer (Receiver) Sensor TelVal[zeile].sTelValHeader = TelVal.Sensors[TelVal[zeile].iTelValParamIdx].label TelVal[zeile].sTelValEinheit = TelVal.Sensors[TelVal[zeile].iTelValParamIdx].unit TelVal[zeile].iTelValNachkomma = TelVal.Sensors[TelVal[zeile].iTelValParamIdx].decimals end -- Die aktuellen Werte löschen TelVal[zeile].fTelValAct = 0.0 TelVal[zeile].fTelValMin = 0.0 TelVal[zeile].fTelValMax = 0.0 end form.reinit(1) end) if bSensorListeReset then TelVal[zeile].iTelValSensorNo = 1 bSensorListeReset = false end -- Einheit zuordnen addRow(2) text = trans.menu_TelValEinheit addLabel({label=text, width=220}) addTextbox(TelVal[zeile].sTelValEinheit, 63, function(value) TelVal[zeile].sTelValEinheit = value end) -- Eingabewert als Schalter oder Geber addRow(2) addLabel({label=trans.menu_FlexPicSwitch, width=230}) addInputbox(TelVal[zeile].swTelVal, true, function(value) if (not isSwitch(value)) then value = nil end TelVal[zeile].swTelVal = value TelVal[zeile].sTelValSensor = "Geber" TelVal[zeile].sTelValParam = "Geber" TelVal[zeile].sTelValHeader = "Geber" TelVal[zeile].sTelValEinheit = "%" TelVal[zeile].iTelValNachkomma = 1 local swInfo = system.getSwitchInfo(TelVal[zeile].swTelVal) if(swInfo ~= nil) then TelVal[zeile].sTelValHeader = swInfo.label TelVal[zeile].sTelValParam = swInfo.label end -- Sensorwerte zurücksetzen TelVal[zeile].iTelValSensorID = 0 TelVal[zeile].iTelValSensorNo = 1 TelVal[zeile].iTelValSensorIdx = 1 TelVal[zeile].bTelValSensorNoName = false TelVal[zeile].iTelValParamNo = 1 TelVal[zeile].iTelValParamIdx = 1 form.reinit(1) end) -- Korrekturfaktor setzen addRow(2) text = trans.menu_TelValKorrekturfaktor addLabel({label=text, width=240}) text = string.format("%s",TelVal[zeile].sTelValKorrekturfaktor) addTextbox(text, 63, function(value) TelVal[zeile].sTelValKorrekturfaktor = value end) -- Nachkommastellen setzen addRow(2) text = trans.menu_TelValNachKommastellen addLabel({label=text, width=270}) addIntbox(TelVal[zeile]["iTelValNachkomma"], 0, 3, TelVal[zeile]["iTelValNachkomma"], 0, 1, function(value) TelVal[zeile]["iTelValNachkomma"] = value end) -- Ansage Wert bei Schalterbetätigung addRow(2) addLabel({label=trans.menu_SpKaAkTkAnsageWert, width=240}) addInputbox(TelVal[zeile].swValPlay, true, function(value) if (not isSwitch(value)) then value = nil end TelVal[zeile].swValPlay = value -- Werte in den Ausgangszustand TelVal[zeile].bSemaPlay = false -- Initwert Sound nicht wierholt ausgeben, nur einmal TelVal[zeile].bCommandPlay = false -- Kommando zum Einstellen der Sounddatei in die Audioque TelVal[zeile].iLockNewPlay = 0 -- Pause, damit bei Signalschwankungen nicht ständig neue Files in die Audioschlange eingetragen werden. =0 -> freigegeben, >0 -> gesperrt end) -- Filter aktivieren local formFilter addRow(2) addLabel({label=trans.menu_TelValFilter, width=275}) formFilter = addCheckbox(TelVal[zeile].bTVSmooth, function(value) TelVal[zeile].bTVSmooth = not value form.setValue(formFilter, TelVal[zeile].bTVSmooth) end) -- Aussehen der Kachel setzen addSpacer(318, 10) addLabel({label=trans.menu_TelValFormHeader, font=FONT_BOLD}) -- Eingabe der Überschrift der Kachel addRow(2) text = string.format("%s %.0f:", trans.menu_TelValHeader, TelVal[zeile]["iTelValNo"]) addLabel({label=text, width=220}) addTextbox(TelVal[zeile]["sTelValHeader"], 63, function(value) TelVal[zeile]["sTelValHeader"] = value end) -- Eingabe der horizontalen Ausrichtung des Headers form.addRow(2) addLabel({label=trans.menu_TelValHeaderHor, width=270}) addIntbox(TelVal[zeile]["iTelValAllignmentHorizontal"], 1, 3, TelVal[zeile]["iTelValAllignmentHorizontal"], 0, 1, function(value) TelVal[zeile]["iTelValAllignmentHorizontal"] = value end) -- Eingabe der Kachelgröße -- Höhe --> -- 0 = mini --> 14 Pixel -- 1 = small --> 18 Pixel -- 2 = normal --> 36 Pixel -- 3 = big --> 52 Pixel -- 4 = gigant --> 80 Pixel Breite = 314 Pixel form.addRow(2) addLabel({label=trans.menu_TelValSize, width=260}) addIntbox(TelVal[zeile]["iTelValSize"], 0, 4, TelVal[zeile]["iTelValSize"], 0, 1, function(value) TelVal[zeile]["iTelValSize"] = value -- Größe neu einstellen if ( value == 0 ) then -- klein TelVal[zeile]["iTelValHeight"] = 12 TelVal[zeile]["iTelValWidth"] = 128 elseif ( value == 1 ) then -- klein TelVal[zeile]["iTelValHeight"] = 18 TelVal[zeile]["iTelValWidth"] = 128 elseif( value == 2 ) then -- normal TelVal[zeile]["iTelValHeight"] = 36 TelVal[zeile]["iTelValWidth"] = 128 elseif( value == 3 ) then -- groß TelVal[zeile]["iTelValHeight"] = 72 TelVal[zeile]["iTelValWidth"] = 128 elseif( value == 4 ) then -- gigantisch TelVal[zeile]["iTelValHeight"] = 132 TelVal[zeile]["iTelValWidth"] = 314 end end) -- Eingabe der Hintergrundfarbe (Initwert = 0 --> keine Hintergrundfarbe) local sText = trans[string.format("ColName%d", TelVal[zeile].iTelValBgColor)].." " local ColNameForm -- Farbnamen anzeigen addRow(1) ColNameForm = addLabel({label=sText, font=FONT_MINI, alignRight=true}) form.addRow(2) addLabel({label=trans.menu_TelValBgColor, width=260}) addIntbox(TelVal[zeile].iTelValBgColor, 0, 44, TelVal[zeile].iTelValBgColor, 0, 1, function(value) TelVal[zeile].iTelValBgColor = value bShowColorByPrintForm = true changeColorByIndex(value, 255) sText = trans[string.format("ColName%d", value)].." " form.setProperties(ColNameForm,{label=sText}) end) -- Warn- und Alarmschwellen setzen addSpacer(318, 10) addLabel({label=trans.menu_TelValWaAlHeader, font=FONT_BOLD}) -- positiven Grenzwert setzen: Warnung addRow(2) text = trans.menu_TelValGrowWarnung addLabel({label=text, width=230}) if (TelVal[zeile].fLimGrowWarning ~= nil) then text = string.format("%.2f",TelVal[zeile].fLimGrowWarning) else text = "---" end addTextbox(text, 63, function(value) if (value == "---") then TelVal[zeile].fLimGrowWarning = nil else TelVal[zeile].fLimGrowWarning = tonumber(value) end end) -- positiven Grenzwert setzen: Alarm addRow(2) text = trans.menu_TelValGrowAlarm addLabel({label=text, width=230}) if (TelVal[zeile].fLimGrowAlarm ~= nil) then text = string.format("%.2f",TelVal[zeile].fLimGrowAlarm) else text = "---" end addTextbox(text, 63, function(value) if (value == "---") then TelVal[zeile].fLimGrowAlarm = nil else TelVal[zeile].fLimGrowAlarm = tonumber(value) end end) -- negativen Grenzwert setzen: Warnung addRow(2) text = trans.menu_TelValShrkWarnung addLabel({label=text, width=230}) if (TelVal[zeile].fLimShrkWarning ~= nil) then text = string.format("%.2f",TelVal[zeile].fLimShrkWarning) else text = "---" end addTextbox(text, 63, function(value) if (value == "---") then TelVal[zeile].fLimShrkWarning = nil else TelVal[zeile].fLimShrkWarning = tonumber(value) end end) -- negativen Grenzwert setzen: Alarm addRow(2) text = trans.menu_TelValShrkAlarm addLabel({label=text, width=230}) if (TelVal[zeile].fLimShrkAlarm ~= nil) then text = string.format("%.2f",TelVal[zeile].fLimShrkAlarm) else text = "---" end addTextbox(text, 63, function(value) if (value == "---") then TelVal[zeile].fLimShrkAlarm = nil else TelVal[zeile].fLimShrkAlarm = tonumber(value) end end) -- Blinkgeschwindigkeit setzen addRow(2) text = trans.menu_TelValFlashSpeed addLabel({label=text, width=230}) addIntbox(TelVal[zeile].iLimBlinkenFreqZael, 4, 20, TelVal[zeile].iLimBlinkenFreqZael, 0, 2, function(value) TelVal[zeile].iLimBlinkenFreqZael = value end) addSpacer(318, 10) addLabel({label=trans.menu_TelValTxHeader, font=FONT_BOLD}) -- 1. Grenzwert setzen addRow(2) text = trans.menu_TelValTxLim.." 1" addLabel({label=text, width=230}) if (TelVal[zeile].fTVTxLim1 ~= nil) then text = string.format("%.2f",TelVal[zeile].fTVTxLim1) else text = "---" end addTextbox(text, 63, function(value) if (value == "---") then TelVal[zeile].fTVTxLim1 = nil else TelVal[zeile].fTVTxLim1 = tonumber(value) end end) -- 1. Anzeigetext setzen addRow(2) text = trans.menu_TelValTxText.." 1" addLabel({label=text, width=150}) addTextbox(TelVal[zeile].sTVTxText1, 63, function(value) TelVal[zeile].sTVTxText1 = value end) -- 2. Grenzwert setzen addRow(2) text = trans.menu_TelValTxLim.." 2" addLabel({label=text, width=230}) if (TelVal[zeile].fTVTxLim2 ~= nil) then text = string.format("%.2f",TelVal[zeile].fTVTxLim2) else text = "---" end addTextbox(text, 63, function(value) if (value == "---") then TelVal[zeile].fTVTxLim2 = nil else TelVal[zeile].fTVTxLim2 = tonumber(value) end end) -- 2. Anzeigetext setzen addRow(2) text = trans.menu_TelValTxText.." 2" addLabel({label=text, width=150}) addTextbox(TelVal[zeile].sTVTxText2, 63, function(value) TelVal[zeile].sTVTxText2 = value end) -- 3. Grenzwert setzen addRow(2) text = trans.menu_TelValTxLim.." 3" addLabel({label=text, width=230}) if (TelVal[zeile].fTVTxLim3 ~= nil) then text = string.format("%.2f",TelVal[zeile].fTVTxLim3) else text = "---" end addTextbox(text, 63, function(value) if (value == "---") then TelVal[zeile].fTVTxLim3 = nil else TelVal[zeile].fTVTxLim3 = tonumber(value) end end) -- 3. Anzeigetext setzen addRow(2) text = trans.menu_TelValTxText.." 3" addLabel({label=text, width=150}) addTextbox(TelVal[zeile].sTVTxText3, 63, function(value) TelVal[zeile].sTVTxText3 = value end) -- 4. Grenzwert setzen addRow(2) text = trans.menu_TelValTxLim.." 4" addLabel({label=text, width=230}) if (TelVal[zeile].fTVTxLim4 ~= nil) then text = string.format("%.2f",TelVal[zeile].fTVTxLim4) else text = "---" end addTextbox(text, 63, function(value) if (value == "---") then TelVal[zeile].fTVTxLim4 = nil else TelVal[zeile].fTVTxLim4 = tonumber(value) end end) -- 4. Anzeigetext setzen addRow(2) text = trans.menu_TelValTxText.." 4" addLabel({label=text, width=150}) addTextbox(TelVal[zeile].sTVTxText4, 63, function(value) TelVal[zeile].sTVTxText4 = value end) -- FlexPic Projektierung elseif (se.option == 3) then local iAccOfFlexPics = FlexPics.iAccOfFlexPic if (FlexPics.iActFlexPicProj == nil) then FlexPics.iActFlexPicProj = 1 end local zeile = string.format("iFlexPicIdx%d", FlexPics.iActFlexPicProj) local sFlexPicVar -- Kurzbezeichnung, damit nicht so viele Buchstaben in das Speicherfile geschrieben werden. bShowColorByPrintForm = true -- Einen Farbbalken anzeigen changeColorByIndex(FlexPics[zeile].iFlexPicBgColor, 255) addRow(3) text = string.format("%s %.0f", trans.menu_FlexPicNums, iAccOfFlexPics) addLabel({label=text, width=180}) addIntbox(variables.iActShownFlexPic, 1, iAccOfFlexPics, FlexPics.iActFlexPicProj, 0, 1, function(value) variables.iActShownFlexPic = value end) form.addLink( updateFlexPicForm, {label="v", alignRight=true, width=20}) -- +++++ Auswahl des Eingabeelementes +++++ -- +++++ Welches FlexPic soll nun projektiert werden? +++++ addRow(2) addLabel({label=trans.menu_FlexPicSwitch, width=230}) addInputbox(FlexPics[zeile].swFlexPic, true, function(value) if (not isSwitch(value)) then value = nil end FlexPics[zeile].swFlexPic = value end) -- Eingabe des FlexPicNamens. Für die Anzeige in der Projektierung. Ggf. muss der Name entfernt werden (Redundante Information) addRow(2) text = string.format("%s%.0f:", trans.menu_FlexPicName, FlexPics[zeile]["iFlexPicNo"]) addLabel({label=text, width=170}) addTextbox(FlexPics[zeile]["sFlexPicName"], 63, function(value) FlexPics[zeile]["sFlexPicName"] = value end) -- Eingabe der Überschrift der Kachel addRow(2) text = string.format("%s%.0f:", trans.menu_FlexPicHeader, FlexPics[zeile]["iFlexPicNo"]) addLabel({label=text, width=170}) addTextbox(FlexPics[zeile]["sFlexPicHeader"], 63, function(value) FlexPics[zeile]["sFlexPicHeader"] = value end) -- Eingabe der horizontalen Ausrichtung des Headers form.addRow(2) addLabel({label=trans.menu_FlexPicHeaderHor, width=270}) addIntbox(FlexPics[zeile]["iFlexPicAllignmentHorizontal"], 1, 3, FlexPics[zeile]["iFlexPicAllignmentHorizontal"], 0, 1, function(value) FlexPics[zeile]["iFlexPicAllignmentHorizontal"] = value end) -- Eingabe der vertikalen Ausrichtung des Headers form.addRow(2) addLabel({label=trans.menu_FlexPicHeaderVer, width=270}) addIntbox(FlexPics[zeile]["iFlexPicAllignmentVertikal"], 1, 3, FlexPics[zeile]["iFlexPicAllignmentVertikal"], 0, 1, function(value) FlexPics[zeile]["iFlexPicAllignmentVertikal"] = value end) -- Überschrift Dateinamen eingeben addRow(2) text = trans.menu_FlexPicEnterFileNames.." [*.png, *.jpg]" addLabel({label=text, font=FONT_BOLD, width=275}) local iImageIndex -- 1. Bild-Dateinamen auswählen if ( (FlexPics[zeile].iFlexPicLastSelectedIndex ~= nil) and (FlexPics[zeile].iFlexPicFileIndex1 == 1) ) then iImageIndex = FlexPics[zeile].iFlexPicLastSelectedIndex FlexPics[zeile].iFlexPicFileIndex1 = iImageIndex FlexPics[zeile].sFlexPicFileName1 = filesImage[iImageIndex] else iImageIndex = FlexPics[zeile].iFlexPicFileIndex1 end form.addRow(2) addLabel({label=trans.menu_FlexPicFileNameGra1, width=220}) addSelectbox(filesImage, iImageIndex, true, function(value) FlexPics[zeile].sFlexPicFileName1 = filesImage[value] FlexPics[zeile].iFlexPicFileIndex1 = value FlexPics[zeile].iFlexPicLastSelectedIndex = value -- Ein Bild wurde ausgewählt FlexPics[zeile]["bFlexPicChanged1"] = true form.reinit(1) end) -- 2. Bild-Dateinamen auswählen if ( (FlexPics[zeile].iFlexPicLastSelectedIndex ~= nil) and (FlexPics[zeile].iFlexPicFileIndex2 == 1) ) then iImageIndex = FlexPics[zeile].iFlexPicLastSelectedIndex FlexPics[zeile].iFlexPicFileIndex2 = iImageIndex FlexPics[zeile].sFlexPicFileName2 = filesImage[iImageIndex] else iImageIndex = FlexPics[zeile].iFlexPicFileIndex2 end form.addRow(2) addLabel({label=trans.menu_FlexPicFileNameGra2, width=220}) addSelectbox(filesImage, iImageIndex, true, function(value) FlexPics[zeile].sFlexPicFileName2 = filesImage[value] FlexPics[zeile].iFlexPicFileIndex2 = value FlexPics[zeile].iFlexPicLastSelectedIndex = value -- Ein Bild wurde ausgewählt FlexPics[zeile].bFlexPicChanged2 = true form.reinit(1) end) -- 3. Bild-Dateinamen auswählen if ( (FlexPics[zeile].iFlexPicLastSelectedIndex ~= nil) and (FlexPics[zeile].iFlexPicFileIndex3 == 1) ) then iImageIndex = FlexPics[zeile].iFlexPicLastSelectedIndex FlexPics[zeile].iFlexPicFileIndex3 = iImageIndex FlexPics[zeile].sFlexPicFileName3 = filesImage[iImageIndex] else iImageIndex = FlexPics[zeile].iFlexPicFileIndex3 end form.addRow(2) addLabel({label=trans.menu_FlexPicFileNameGra3, width=220}) addSelectbox(filesImage, iImageIndex, true, function(value) FlexPics[zeile].sFlexPicFileName3 = filesImage[value] FlexPics[zeile].iFlexPicFileIndex3 = value FlexPics[zeile].iFlexPicLastSelectedIndex = value -- Ein Bild wurde ausgewählt FlexPics[zeile].bFlexPicChanged3 = true form.reinit(1) end) -- Eingabe der Bildhöhe (Default = 38 'Pixel') form.addRow(2) addLabel({label=trans.menu_FlexPicHeight.." (16 - 234)", width=250}) addIntbox(FlexPics[zeile].iFlexPicHeight, 16, 234, FlexPics[zeile].iFlexPicHeight, 0, 1, function(value) FlexPics[zeile]["iFlexPicHeight"] = value end) -- Eingabe der Hintergrundfarbe (Initwert = 0 --> keine Hintergrundfarbe) local sText = trans[string.format("ColName%d", FlexPics[zeile].iFlexPicBgColor)].." " local ColNameForm -- Farbnamen anzeigen addRow(1) ColNameForm = addLabel({label=sText, font=FONT_MINI, alignRight=true}) form.addRow(2) addLabel({label=trans.menu_FlexPicBgColor, width=260}) addIntbox(FlexPics[zeile].iFlexPicBgColor, 0, 44, FlexPics[zeile].iFlexPicBgColor, 0, 1, function(value) FlexPics[zeile].iFlexPicBgColor = value changeColorByIndex(value, 255) bShowColorByPrintForm = true -- Keinen Farbbalken anzeigen sText = trans[string.format("ColName%d", value)].." " form.setProperties(ColNameForm,{label=sText}) end) -- Überschrift Grenzwerte eingeben addRow(2) text = trans.menu_FlexPicEnterLimits.." [-150% <-> +150%]" addLabel({label=text, font=FONT_BOLD, width=275}) -- Grenzwert Zustand 1 nach 2 form.addRow(2) addLabel({label=trans.menu_FlexPicLimit12, width=260}) addIntbox(FlexPics[zeile]["fFlexPicLim12"], -200, 200, FlexPics[zeile]["fFlexPicLim12"], 0, 1, function(value) FlexPics[zeile]["fFlexPicLim12"] = value end) -- Grenzwert Zustand 2 nach 3 form.addRow(2) addLabel({label=trans.menu_FlexPicLimit23, width=260}) addIntbox(FlexPics[zeile]["fFlexPicLim23"], -200, 200, FlexPics[zeile]["fFlexPicLim23"], 0, 1, function(value) FlexPics[zeile]["fFlexPicLim23"] = value end) -- Grenzwert Zustand 3 nach 2 form.addRow(2) addLabel({label=trans.menu_FlexPicLimit32, width=260}) addIntbox(FlexPics[zeile]["fFlexPicLim32"], -200, 200, FlexPics[zeile]["fFlexPicLim32"], 0, 1, function(value) FlexPics[zeile]["fFlexPicLim32"] = value end) -- Grenzwert Zustand 2 nach 1 form.addRow(2) addLabel({label=trans.menu_FlexPicLimit21, width=260}) addIntbox(FlexPics[zeile]["fFlexPicLim21"], -200, 200, FlexPics[zeile]["fFlexPicLim21"], 0, 1, function(value) FlexPics[zeile]["fFlexPicLim21"] = value end) --Spezial-Kacheln: Balkenanzeige (BarChart) Säulendiagramm elseif (se.option == 4) then local bAnsageRestmengeForm, bGrowing1Form, bGrowing2Form, bShowScaleForm, ParameterList, ParameterListIdx local bConvertGrowToShrk1Form, bConvertGrowToShrk2Form local againForm1, againForm2 addRow(2) addLabel({label=trans.menu_SpKaAkTk, font=FONT_BOLD}) -- Anzahl der Akkus/Tankbehälter addRow(2) addLabel({label=trans.menu_SpKaAkTkAnzahl, width=260}) addIntbox(SpecTiles.AkkuTank.iAccOfStorage, 1, 2, SpecTiles.AkkuTank.iAccOfStorage, 0, 1, function(value) -- Prüfen, ob eine Änderung eingestellt ist if(SpecTiles.AkkuTank.iAccOfStorage ~= value)then -- Es wurde eine andere Anzahl angewählt --> Menü aktualisieren SpecTiles.AkkuTank.iAccOfStorage = value form.reinit(1) end end) -- Sensoren / Geber auswählen addSpacer(318, 10) if (SpecTiles.AkkuTank.iAccOfStorage == 1) then addLabel({label=trans.menu_TelValSensHeader, font=FONT_BOLD}) else addLabel({label=trans.menu_TelValSensHeader.." 1", font=FONT_BOLD}) end -- Sensor1 auswählen addRow(2) if (SpecTiles.AkkuTank.iAccOfStorage == 1) then addLabel({label=trans.menu_SpKaAkTkSensorNo, width=150}) else addLabel({label=trans.menu_SpKaAkTkSensorNo.." 1", width=150}) end addSelectbox(TelVal.SensorListLabel, SpecTiles.AkkuTank.iSensorNo1, true, function(value) SpecTiles.AkkuTank.iSensorNo1 = value SpecTiles.AkkuTank.sSensorName1 = TelVal.SensorListLabel[value] SpecTiles.AkkuTank.iSensorId1 = TelVal.SensorListId[value] SpecTiles.AkkuTank.iSensorType1 = TelVal.SensorListType[value] -- Jetzt werden die derzeit noch eingestellten Sensorwerte zurückgesetzt SpecTiles.AkkuTank.sSensorValueName1 = "..." SpecTiles.AkkuTank.iSensorValueNo1 = 1 SpecTiles.AkkuTank.iSensorValueIdx1 = 1 SpecTiles.AkkuTank.sSensorUnit1 = " " -- Sensorwertlisten richtig verwenden/anzeigen form.reinit(1) end) -- Sensorwert1 auswählen addRow(2) if (SpecTiles.AkkuTank.iAccOfStorage == 1) then addLabel({label=trans.menu_SpKaAkTkSensorValueNo, width=150}) else addLabel({label=trans.menu_SpKaAkTkSensorValueNo.." 1", width=150}) end -- Sicherheitsabfrage if(SpecTiles.AkkuTank.iSensorNo1 <= 1)then SpecTiles.AkkuTank.iSensorNo1 = 2 -- muß mindestens 2 sein -> kein Sensor angewählt bSensorListeReset = true else bSensorListeReset = false end ParameterList = string.format("SensorListWertLabel%d", SpecTiles.AkkuTank.iSensorNo1 - 1) -- Der erste Wert ist der NULL-Wert ParameterListIdx = string.format("SensorListWertLabelIdx%d", SpecTiles.AkkuTank.iSensorNo1 - 1 ) -- Der erste Wert ist der NULL-Wert addSelectbox( TelVal[ParameterList], SpecTiles.AkkuTank.iSensorValueNo1, true, function(value) if (value == 1) then SpecTiles.AkkuTank.sSensorValueName1 = "..." SpecTiles.AkkuTank.iSensorValueNo1 = 1 SpecTiles.AkkuTank.iSensorValueIdx1 = 1 SpecTiles.AkkuTank.sSensorUnit1 = " " else SpecTiles.AkkuTank.iSensorValueNo1 = value SpecTiles.AkkuTank.sSensorValueName1 = TelVal[ParameterList][value] SpecTiles.AkkuTank.iSensorValueIdx1 = TelVal[ParameterListIdx][value] if (SpecTiles.AkkuTank.iSensorType1 == 2) then -- Interne Sensoreinheit SpecTiles.AkkuTank.sSensorUnit1 = variables.Sensors[SpecTiles.AkkuTank.iSensorValueIdx1].unit else -- Externe Sensoreinheit SpecTiles.AkkuTank.sSensorUnit1 = TelVal.Sensors[SpecTiles.AkkuTank.iSensorValueIdx1].unit end end form.reinit(1) end) if bSensorListeReset then SpecTiles.AkkuTank.iSensorNo1 = 1 bSensorListeReset = false end -- Sensoreinheit 1 addRow(2) if (SpecTiles.AkkuTank.iAccOfStorage == 1) then addLabel({label=trans.menu_SpKaAkTkSensorUnit, width=200}) else addLabel({label=trans.menu_SpKaAkTkSensorUnit.." 1", width=200}) end text = string.format("%s", SpecTiles.AkkuTank.sSensorUnit1) addTextbox(text, 63, function(value) SpecTiles.AkkuTank.sSensorUnit1 = value form.reinit(1) end) -- Korrekturfaktor 1 addRow(2) if (SpecTiles.AkkuTank.iAccOfStorage == 1) then addLabel({label=trans.menu_TelValKorrekturfaktor, width=220}) else addLabel({label=trans.menu_TelValKorrekturfaktor.." 1", width=220}) end text = string.format("%s", SpecTiles.AkkuTank.sKorrekturfaktor1) addTextbox(text, 63, function(value) SpecTiles.AkkuTank.sKorrekturfaktor1 = value end) -- Fassungsvermögen 1 addRow(2) if (SpecTiles.AkkuTank.iAccOfStorage == 1) then text = string.format("%s [%s]", trans.menu_SpKaAkTkCapacity, SpecTiles.AkkuTank.sSensorUnit1) addLabel({label=text, width=240}) else text = string.format("%s1 [%s]", trans.menu_SpKaAkTkCapacity, SpecTiles.AkkuTank.sSensorUnit1) addLabel({label=text, width=240}) end local iMax, iMin if SpecTiles.AkkuTank.bConvertGrowToShrk1 then -- Min-Maxiwert ist 100% iMin = 1 iMax = 100 else -- normaler Min-Maxwert iMin = 10 iMax = 10000 end addIntbox(SpecTiles.AkkuTank.iCapacity1, iMin, iMax, SpecTiles.AkkuTank.iCapacity1, 0, 10, function(value) SpecTiles.AkkuTank.iCapacity1 = value end) -- Sensorwert wachsend 1 (Default = false = fallend) addRow(2) if (SpecTiles.AkkuTank.iAccOfStorage == 1) then addLabel({label=trans.menu_SpKaAkTkGrowing, width=275}) else addLabel({label=trans.menu_SpKaAkTkGrowing.." 1", width=275}) end bGrowing1Form = addCheckbox(SpecTiles.AkkuTank.bGrowing1, function(value) SpecTiles.AkkuTank.bGrowing1 = not value form.setValue(bGrowing1Form, SpecTiles.AkkuTank.bGrowing1) if SpecTiles.AkkuTank.iConvGtoScapacity1 ~= SpecTiles.AkkuTank.iCapacity1 then -- Bei Ungleichheit zurückspeichern SpecTiles.AkkuTank.iCapacity1 = SpecTiles.AkkuTank.iConvGtoScapacity1 end if( SpecTiles.AkkuTank.bGrowing1 and SpecTiles.AkkuTank.bConvertGrowToShrk1) then -- zurücksetzten, da sonst Anzeigekonflikt SpecTiles.AkkuTank.bConvertGrowToShrk1 = false form.reinit(1) end end) -- Umkehrung von wachsend zu schumpfend und % Wandlung 1 addRow(2) if (SpecTiles.AkkuTank.iAccOfStorage == 1) then addLabel({label=trans.menu_SpKaAkTkGrowToShrk, width=275}) else addLabel({label=trans.menu_SpKaAkTkGrowToShrk.." 1", width=275}) end bConvertGrowToShrk1Form = addCheckbox(SpecTiles.AkkuTank.bConvertGrowToShrk1, function(value) SpecTiles.AkkuTank.bConvertGrowToShrk1 = not value form.setValue(bConvertGrowToShrk1Form, SpecTiles.AkkuTank.bConvertGrowToShrk1) if SpecTiles.AkkuTank.iConvGtoScapacity1 ~= SpecTiles.AkkuTank.iCapacity1 then -- Bei Ungleichheit speichern SpecTiles.AkkuTank.iConvGtoScapacity1 = SpecTiles.AkkuTank.iCapacity1 end if( SpecTiles.AkkuTank.bGrowing1 and SpecTiles.AkkuTank.bConvertGrowToShrk1) then -- zurücksetzten, da sonst Anzeigekonflikt SpecTiles.AkkuTank.bGrowing1 = false form.reinit(1) end end) -- Warn- und Alarmschwellen setzen 1 addSpacer(318, 10) if (SpecTiles.AkkuTank.iAccOfStorage == 1) then addLabel({label=trans.menu_TelValWaAlHeader, font=FONT_BOLD}) else addLabel({label=trans.menu_TelValWaAlHeader.." 1", font=FONT_BOLD}) end -- Warnschwelle 1 addRow(2) if (SpecTiles.AkkuTank.iAccOfStorage == 1) then addLabel({label=trans.menu_SpKaAkTkWarningValue, width=240}) else addLabel({label=trans.menu_SpKaAkTkWarningValue.." 1 ["..SpecTiles.AkkuTank.sSensorUnit1.."]", width=240}) end if SpecTiles.AkkuTank.bConvertGrowToShrk1 then -- Min-Maxiwert ist 100% iMin = 1 iMax = 100 else -- normaler Min-Maxwert iMin = 10 iMax = 10000 end addIntbox(SpecTiles.AkkuTank.iWarningValue1, iMin, iMax, SpecTiles.AkkuTank.iWarningValue1, 0, 1, function(value) SpecTiles.AkkuTank.iWarningValue1 = value end) -- Alarmschwelle 1 addRow(2) if (SpecTiles.AkkuTank.iAccOfStorage == 1) then addLabel({label=trans.menu_SpKaAkTkAlarmValue, width=240}) else addLabel({label=trans.menu_SpKaAkTkAlarmValue.." 1 ["..SpecTiles.AkkuTank.sSensorUnit1.."]", width=240}) end addIntbox(SpecTiles.AkkuTank.iAlarmValue1, 1, 10000, SpecTiles.AkkuTank.iAlarmValue1, 0, 1, function(value) SpecTiles.AkkuTank.iAlarmValue1 = value end) -- Werte übenehmen? 1 -- Gibt es übernehmbare Werte if ( (SpecTiles.calcaElec ~= nil) or (SpecTiles.calcaFuel ~= nil) or (SpecTiles.calcaPlus ~= nil) ) then -- Ja es gibt Werte local iSource if SpecTiles.calcaElec ~= nil then text = string.format("%s %s", trans.menu_SpKaAkTkWerteVon, variables.Sensors[variables.Calca70Idx].label) iSource = 1 elseif SpecTiles.calcaFuel ~= nil then text = string.format("%s %s", trans.menu_SpKaAkTkWerteVon, variables.Sensors[variables.FuelIdx].label) iSource = 2 elseif SpecTiles.calcaPlus ~= nil then text = string.format("%s %s", trans.menu_SpKaAkTkWerteVon, variables.Sensors[variables.calcaPlusIdx].label) iSource = 3 else -- keine Datenübernahme iSource = 0 end -- Abfrage, ob Werte übernommen werden sollen addRow(2) addLabel({label=text, width=275}) variables.WertVonForm = addCheckbox(variables.WertVon, function(value) variables.WertVon = not value form.setValue(variables.WertVonForm, variables.WertVon) -- gecheckt anzeigen -- Werte übernehmen if iSource == 1 then -- calca-Elec SpecTiles.AkkuTank.sRepresentation1 = string.format("%d",SpecTiles.calcaElec.batteryCapacity) SpecTiles.AkkuTank.sRepresentUnit1 = "mAh" SpecTiles.AkkuTank.iWarningValue1 = SpecTiles.calcaElec.preAlarmPercent SpecTiles.AkkuTank.iAlarmValue1 = SpecTiles.calcaElec.mainAlarmPercent form.reinit(1) elseif iSource == 2 then -- calca-Fuel SpecTiles.AkkuTank.sRepresentation1 = string.format("%d",SpecTiles.calcaFuel.tankCapacity) SpecTiles.AkkuTank.sRepresentUnit1 = "ml" SpecTiles.AkkuTank.iWarningValue1 = SpecTiles.calcaFuel.preAlarmPercent SpecTiles.AkkuTank.iAlarmValue1 = SpecTiles.calcaFuel.mainAlarmPercent form.reinit(1) elseif iSource == 3 then -- calca-Plus SpecTiles.AkkuTank.sRepresentation1 = string.format("%d",SpecTiles.calcaPlus.batteryCapacity) SpecTiles.AkkuTank.sRepresentUnit1 = "mAh" SpecTiles.AkkuTank.iWarningValue1 = SpecTiles.calcaPlus.preAlarmPercent SpecTiles.AkkuTank.iAlarmValue1 = SpecTiles.calcaPlus.mainAlarmPercent form.reinit(1) end end) end -- WarnSound 1 addRow(2) if (SpecTiles.AkkuTank.iAccOfStorage == 1) then addLabel({label=trans.menu_SpKaAkTkWarningSound, width=240}) else addLabel({label=trans.menu_SpKaAkTkWarningSound.." 1", width=240}) end addAudioFilebox(SpecTiles.AkkuTank.sWarningSound1, function(value) SpecTiles.AkkuTank.sWarningSound1 = value end) -- AlarmSound 1 addRow(2) if (SpecTiles.AkkuTank.iAccOfStorage == 1) then addLabel({label=trans.menu_SpKaAkTkAlarmSound, width=240}) else addLabel({label=trans.menu_SpKaAkTkAlarmSound.." 1", width=240}) end addAudioFilebox(SpecTiles.AkkuTank.sAlarmSound1, function(value) SpecTiles.AkkuTank.sAlarmSound1 = value end) -- Ansage Wert bei Schalterbetätigung addRow(2) if (SpecTiles.AkkuTank.iAccOfStorage == 1) then addLabel({label=trans.menu_SpKaAkTkAnsageWert, width=240}) else addLabel({label=trans.menu_SpKaAkTkAnsageWert.." 1", width=240}) end addInputbox(SpecTiles.AkkuTank.swValPlay1, true, function(value) if (not isSwitch(value)) then value = nil end SpecTiles.AkkuTank.swValPlay1 = value end) -- 3x Wiederholen 1 addRow(2) if (SpecTiles.AkkuTank.iAccOfStorage == 1) then addLabel({label=trans.again, width=275}) else addLabel({label=trans.again.." 1", width=275}) end againForm1 = addCheckbox(se.again1, function(value) se.again1 = not value form.setValue(againForm1, se.again1) end) -- Aussehen der Kachel setzen 1 addSpacer(318, 10) if (SpecTiles.AkkuTank.iAccOfStorage == 1) then addLabel({label=trans.menu_TelValFormHeader, font=FONT_BOLD}) else addLabel({label=trans.menu_TelValFormHeader.." 1", font=FONT_BOLD}) end -- Beschriftung Fußzeile maximaler physikalischer Wert 1 addRow(2) if (SpecTiles.AkkuTank.iAccOfStorage == 1) then addLabel({label=trans.menu_SpKaAkTkBeschriftung, width=240}) else addLabel({label=trans.menu_SpKaAkTkBeschriftung.." 1", width=240}) end addTextbox(SpecTiles.AkkuTank.sRepresentation1, 8, function(value) SpecTiles.AkkuTank.sRepresentation1 = value end) -- Beschriftung Fußzeile physikalische Einheit 1 addRow(2) if (SpecTiles.AkkuTank.iAccOfStorage == 1) then addLabel({label=trans.menu_SpKaAkTkBeschriftungEinheit, width=240}) else addLabel({label=trans.menu_SpKaAkTkBeschriftungEinheit.." 1", width=240}) end addTextbox(SpecTiles.AkkuTank.sRepresentUnit1, 8, function(value) SpecTiles.AkkuTank.sRepresentUnit1 = value end) -- Projektierung der 2. Balkenanzeige ------------------------------------- if( SpecTiles.AkkuTank.iAccOfStorage == 2) then -- 2 Batterien/Tanks projektieren addSpacer(318, 10) addLabel({label=trans.menu_TelValSensHeader.." 2", font=FONT_BOLD}) -- Sensor2 auswählen addRow(2) addLabel({label=trans.menu_SpKaAkTkSensorNo.." 2", width=150}) addSelectbox(TelVal.SensorListLabel, SpecTiles.AkkuTank.iSensorNo2, true, function(value) SpecTiles.AkkuTank.iSensorNo2 = value SpecTiles.AkkuTank.sSensorName2 = TelVal.SensorListLabel[value] SpecTiles.AkkuTank.iSensorId2 = TelVal.SensorListId[value] SpecTiles.AkkuTank.iSensorType2 = TelVal.SensorListType[value] -- Jetzt werden die derzeit noch eingestellten Sensorwerte zurückgesetzt SpecTiles.AkkuTank.sSensorValueName2 = "..." SpecTiles.AkkuTank.iSensorValueNo2 = 1 SpecTiles.AkkuTank.iSensorValueIdx2 = 1 SpecTiles.AkkuTank.sSensorUnit2 = " " -- Sensorwertlisten richtig verwenden/anzeigen form.reinit(1) end) -- Sensorwert2 auswählen addRow(2) addLabel({label=trans.menu_SpKaAkTkSensorValueNo.." 2", width=150}) -- Sicherheitsabfrage if(SpecTiles.AkkuTank.iSensorNo2 <= 1)then SpecTiles.AkkuTank.iSensorNo2 = 2 -- muß mindestens 1 sein -> kein Sensor angewählt bSensorListeReset = true else bSensorListeReset = false end ParameterList = string.format("SensorListWertLabel%d", SpecTiles.AkkuTank.iSensorNo2 - 1) -- Der erste Wert ist der NULL-Wert ParameterListIdx = string.format("SensorListWertLabelIdx%d", SpecTiles.AkkuTank.iSensorNo2 - 1 ) -- Der erste Wert ist der NULL-Wert addSelectbox( TelVal[ParameterList], SpecTiles.AkkuTank.iSensorValueNo2, true, function(value) if (value == 1) then SpecTiles.AkkuTank.sSensorValueName2 = "..." SpecTiles.AkkuTank.iSensorValueNo2 = 1 SpecTiles.AkkuTank.iSensorValueIdx2 = 1 SpecTiles.AkkuTank.sSensorUnit2 = " " else SpecTiles.AkkuTank.iSensorValueNo2 = value SpecTiles.AkkuTank.sSensorValueName2 = TelVal[ParameterList][value] SpecTiles.AkkuTank.iSensorValueIdx2 = TelVal[ParameterListIdx][value] if (SpecTiles.AkkuTank.iSensorType2 == 2) then -- Interne Sensoreinheit SpecTiles.AkkuTank.sSensorUnit2 = variables.Sensors[SpecTiles.AkkuTank.iSensorValueIdx2].unit else -- Externe Sensoreinheit SpecTiles.AkkuTank.sSensorUnit2 = TelVal.Sensors[SpecTiles.AkkuTank.iSensorValueIdx2].unit end end form.reinit(1) end) if bSensorListeReset then SpecTiles.AkkuTank.iSensorNo2 = 1 bSensorListeReset = false end -- Sensoreinheit 2 addRow(2) addLabel({label=trans.menu_SpKaAkTkSensorUnit.." 2", width=200}) text = string.format("%s", SpecTiles.AkkuTank.sSensorUnit2) addTextbox(text, 63, function(value) SpecTiles.AkkuTank.sSensorUnit2 = value form.reinit(1) end) -- Korrekturfaktor 2 addRow(2) addLabel({label=trans.menu_TelValKorrekturfaktor.." 2", width=220}) text = string.format("%s", SpecTiles.AkkuTank.sKorrekturfaktor2) addTextbox(text, 63, function(value) SpecTiles.AkkuTank.sKorrekturfaktor2 = value end) -- Fassungsvermögen 2 addRow(2) addLabel({label=trans.menu_SpKaAkTkCapacity.." 2 ["..SpecTiles.AkkuTank.sSensorUnit2.."])", width=240}) if SpecTiles.AkkuTank.bConvertGrowToShrk2 then -- Min-Maxiwert ist 100% iMin = 1 iMax = 100 else -- normaler Min-Maxwert iMin = 10 iMax = 10000 end addIntbox(SpecTiles.AkkuTank.iCapacity2, 10, iMax, SpecTiles.AkkuTank.iCapacity2, 0, 10, function(value) SpecTiles.AkkuTank.iCapacity2 = value end) -- Sensorwert wachsend 2 (Default = false = fallend) addRow(2) addLabel({label=trans.menu_SpKaAkTkGrowing.." 2", width=275}) bGrowing2Form = addCheckbox(SpecTiles.AkkuTank.bGrowing2, function(value) SpecTiles.AkkuTank.bGrowing2 = not value form.setValue(bGrowing2Form, SpecTiles.AkkuTank.bGrowing2) if SpecTiles.AkkuTank.iConvGtoScapacity2 ~= SpecTiles.AkkuTank.iCapacity2 then -- Bei Ungleichheit zurückspeichern SpecTiles.AkkuTank.iCapacity2 = SpecTiles.AkkuTank.iConvGtoScapacity2 end if( SpecTiles.AkkuTank.bGrowing2 and SpecTiles.AkkuTank.bConvertGrowToShrk2) then -- zurücksetzten, da sonst Anzeigekonflikt SpecTiles.AkkuTank.bConvertGrowToShrk2 = false form.reinit(1) end end) -- Umkehrung von wachsend zu schumpfend und % Wandlung 2 addRow(2) addLabel({label=trans.menu_SpKaAkTkGrowToShrk.." 2", width=275}) bConvertGrowToShrk2Form = addCheckbox(SpecTiles.AkkuTank.bConvertGrowToShrk2, function(value) SpecTiles.AkkuTank.bConvertGrowToShrk2 = not value form.setValue(bConvertGrowToShrk2Form, SpecTiles.AkkuTank.bConvertGrowToShrk2) if SpecTiles.AkkuTank.iConvGtoScapacity2 ~= SpecTiles.AkkuTank.iCapacity2 then -- Bei Ungleichheit speichern SpecTiles.AkkuTank.iConvGtoScapacity2 = SpecTiles.AkkuTank.iCapacity2 end if( SpecTiles.AkkuTank.bGrowing2 and SpecTiles.AkkuTank.bConvertGrowToShrk2) then -- zurücksetzten, da sonst Anzeigekonflikt SpecTiles.AkkuTank.bGrowing2 = false form.reinit(1) end end) -- Warn- und Alarmschwellen setzen 2 addSpacer(318, 10) addLabel({label=trans.menu_TelValWaAlHeader.." 2", font=FONT_BOLD}) -- Warnschwelle 2 addRow(2) addLabel({label=trans.menu_SpKaAkTkWarningValue.." 2 ["..SpecTiles.AkkuTank.sSensorUnit2.."]", width=240}) if SpecTiles.AkkuTank.bConvertGrowToShrk2 then -- Min-Maxiwert ist 100% iMin = 1 iMax = 100 else -- normaler Min-Maxwert iMin = 10 iMax = 10000 end addIntbox(SpecTiles.AkkuTank.iWarningValue2, 1, 10000, SpecTiles.AkkuTank.iWarningValue2, 0, 1, function(value) SpecTiles.AkkuTank.iWarningValue2 = value end) -- Alarmschwelle 2 addRow(2) addLabel({label=trans.menu_SpKaAkTkAlarmValue.." 2 ["..SpecTiles.AkkuTank.sSensorUnit2.."]", width=240}) addIntbox(SpecTiles.AkkuTank.iAlarmValue2, 1, 10000, SpecTiles.AkkuTank.iAlarmValue2, 0, 1, function(value) SpecTiles.AkkuTank.iAlarmValue2 = value end) -- Werte übenehmen? 2 -- Gibt es übernehmbare Werte if ( (SpecTiles.calcaElec ~= nil) or (SpecTiles.calcaFuel ~= nil) or (SpecTiles.calcaPlus ~= nil) ) then -- Ja es gibt Werte local iSource if SpecTiles.calcaElec ~= nil then text = string.format("%s %s", trans.menu_SpKaAkTkWerteVon, variables.Sensors[variables.Calca70Idx].label) iSource = 1 elseif SpecTiles.calcaFuel ~= nil then text = string.format("%s %s", trans.menu_SpKaAkTkWerteVon, variables.Sensors[variables.FuelIdx].label) iSource = 2 elseif SpecTiles.calcaPlus ~= nil then text = string.format("%s %s", trans.menu_SpKaAkTkWerteVon, variables.Sensors[variables.calcaPlusIdx].label) iSource = 3 else -- keine Datenübernahme iSource = 0 end -- Abfrage, ob Werte übernommen werden sollen addRow(2) addLabel({label=text, width=275}) variables.WertVonForm2 = addCheckbox(variables.WertVon2, function(value) variables.WertVon2 = not value form.setValue(variables.WertVonForm2, variables.WertVon2) -- gecheckt anzeigen -- Werte übernehmen if iSource == 1 then -- calca-Elec SpecTiles.AkkuTank.sRepresentation2 = string.format("%d",SpecTiles.calcaElec.batteryCapacity) SpecTiles.AkkuTank.sRepresentUnit1 = "mAh" SpecTiles.AkkuTank.iWarningValue1 = SpecTiles.calcaElec.preAlarmPercent SpecTiles.AkkuTank.iAlarmValue1 = SpecTiles.calcaElec.mainAlarmPercent form.reinit(1) elseif iSource == 2 then -- calca-Fuel SpecTiles.AkkuTank.sRepresentation2 = string.format("%d",SpecTiles.calcaFuel.tankCapacity) SpecTiles.AkkuTank.sRepresentUnit1 = "ml" SpecTiles.AkkuTank.iWarningValue2 = SpecTiles.calcaFuel.preAlarmPercent SpecTiles.AkkuTank.iAlarmValue2 = SpecTiles.calcaFuel.mainAlarmPercent form.reinit(1) elseif iSource == 3 then -- calca-Plus SpecTiles.AkkuTank.sRepresentation2 = string.format("%d",SpecTiles.calcaPlus.batteryCapacity) SpecTiles.AkkuTank.sRepresentUnit1 = "mAh" SpecTiles.AkkuTank.iWarningValue2 = SpecTiles.calcaPlus.preAlarmPercent SpecTiles.AkkuTank.iAlarmValue2 = SpecTiles.calcaPlus.mainAlarmPercent form.reinit(1) end end) end -- WarnSound 2 addRow(2) addLabel({label=trans.menu_SpKaAkTkWarningSound.." 2"}) addAudioFilebox(SpecTiles.AkkuTank.sWarningSound2, function(value) SpecTiles.AkkuTank.sWarningSound2 = value end) -- AlarmSound 2 addRow(2) addLabel({label=trans.menu_SpKaAkTkAlarmSound.." 2"}) addAudioFilebox(SpecTiles.AkkuTank.sAlarmSound2, function(value) SpecTiles.AkkuTank.sAlarmSound2 = value end) -- Ansage Wert 2 bei Schalterbetätigung addRow(2) addLabel({label=trans.menu_SpKaAkTkAnsageWert.." 2", width=240}) addInputbox(SpecTiles.AkkuTank.swValPlay2, true, function(value) if (not isSwitch(value)) then value = nil end SpecTiles.AkkuTank.swValPlay2 = value end) -- 3x Wiederholen 2 addRow(2) addLabel({label=trans.again.." 2", width=275}) againForm2 = addCheckbox(se.again2, function(value) se.again2 = not value form.setValue(againForm2, se.again2) end) -- Aussehen der Kachel setzen 2 addSpacer(318, 10) addLabel({label=trans.menu_TelValFormHeader.." 2", font=FONT_BOLD}) -- Beschriftung Fußzeile maximaler physikalischer Wert 2 addRow(2) addLabel({label=trans.menu_SpKaAkTkBeschriftung.." 2", width=240}) addTextbox(SpecTiles.AkkuTank.sRepresentation2, 8, function(value) SpecTiles.AkkuTank.sRepresentation2 = value end) -- Beschriftung Fußzeile physikalische Einheit 2 addRow(2) addLabel({label=trans.menu_SpKaAkTkBeschriftungEinheit.." 2"}) addTextbox(SpecTiles.AkkuTank.sRepresentUnit2, 8, function(value) SpecTiles.AkkuTank.sRepresentUnit2 = value end) end -- Allgemeine Einstellungen addSpacer(318, 10) addLabel({label=trans.menu_SpKaAkTkAllgemein, font=FONT_BOLD}) -- Ansage Restmenge ja/nein addRow(2) addLabel({label=trans.menu_SpKaAkTkAnnounce, width=275}) bAnsageRestmengeForm = addCheckbox(SpecTiles.AkkuTank.bAnsageRestmenge, function(value) SpecTiles.AkkuTank.bAnsageRestmenge = not value form.setValue(bAnsageRestmengeForm, SpecTiles.AkkuTank.bAnsageRestmenge) end) -- Anzeige Skala ja/nein addRow(2) addLabel({label=trans.menu_SpKaAkTkscale, width=275}) bShowScaleForm = addCheckbox(SpecTiles.AkkuTank.bShowScale, function(value) SpecTiles.AkkuTank.bShowScale = not value form.setValue(bShowScaleForm, SpecTiles.AkkuTank.bShowScale) end) -- Kachelhöhe addRow(2) addLabel({label=trans.menu_SpKaAkTkTilesHeight.."(100...234)", width=240}) addIntbox(SpecTiles.AkkuTank.iTilesHeigtht, 100, 234, SpecTiles.AkkuTank.iTilesHeigtht, 0, 1, function(value) SpecTiles.AkkuTank.iTilesHeigtht = value end) -- Hintergrundbild Akku/Tank form.addRow(2) addLabel({label=trans.menu_SpKaAkTkPicFileName, width=150}) -- Den Index aus dem filesImage-Feld ermitteln for i=1, #filesImage do if (filesImage[i] == SpecTiles.AkkuTank.sPicFileName) then SpecTiles.AkkuTank.iPicFileIndex = i end end addSelectbox(filesImage, SpecTiles.AkkuTank.iPicFileIndex, true, function(value) SpecTiles.AkkuTank.sPicFileName = filesImage[value] SpecTiles.AkkuTank.iPicFileIndex = value -- Ein neues Bild wurde ausgewählt SpecTiles.AkkuTank.bPicFileChanged = true end) -- Eingabe der Hintergrundfarbe (Initwert = 0 --> keine Hintergrundfarbe) local sText = trans[string.format("ColName%d", SpecTiles.AkkuTank.iBgColor)].." " local ColNameForm -- Farbnamen anzeigen addRow(1) ColNameForm = addLabel({label=sText, font=FONT_MINI, alignRight=true}) form.addRow(2) addLabel({label=trans.menu_SpKaAkTkBgColor, width=260}) addIntbox(SpecTiles.AkkuTank.iBgColor, 0, 44, SpecTiles.AkkuTank.iBgColor, 0, 1, function(value) bShowColorByPrintForm = true changeColorByIndex(value, 255) SpecTiles.AkkuTank.iBgColor = value sText = trans[string.format("ColName%d", value)].." " form.setProperties(ColNameForm,{label=sText}) end) -- Eingabe der Transparenz der Farbbalken form.addRow(2) addLabel({label=trans.menu_SpKaTransparenz, width=240}) addIntbox(SpecTiles.AkkuTank.iTransparenz, 0, 255, SpecTiles.AkkuTank.iTransparenz, 0, 1, function(value) SpecTiles.AkkuTank.iTransparenz = value end) elseif (se.option == 5) then -- Zeige/Lösche SnapShot Datei if variables.SnapShot.FileFirstTime then -- Vorauswahl, die letzte SnapShot-Datei einstellen (letzter Eintrag) variables.SnapShot.FileIndex = #variables.SnapShot.Files variables.SnapShot.FileName = variables.SnapShot.Files[variables.SnapShot.FileIndex] variables.SnapShot.FileFirstTime = false end -- Datei wählen form.addRow(2) addLabel({label=trans.menu_ShowSnapshotFile, width=150}) addSelectbox(variables.SnapShot.Files, variables.SnapShot.FileIndex, true, function(value) variables.SnapShot.FileName = variables.SnapShot.Files[value] variables.SnapShot.FileIndex = value -- Alte angezeigte Daten löschen form.reinit(1) -- Neue Daten anzeigen if (variables.SnapShot.FileName:len() > 0) then local file = io.open(folder..variables.SnapShot.FileName..extensionFile, "r") addSpacer(318, 10) if (file) then local line line = io.readline(file) addRow(2) addLabel({label=line, width=280, font=FONT_BOLD}) repeat line = io.readline(file) addRow(2) addLabel({label=line, width=280}) until (not line) io.close(file) end end end) -- Datei löschen form.addRow(2) addLabel({label=trans.menu_EraseSnapshotFile, width=150}) addSelectbox(variables.SnapShot.Files, variables.SnapShot.FileEraseIndex, true, function(value) variables.SnapShot.FileEraseName = variables.SnapShot.Files[value] variables.SnapShot.FileEraseIndex = value if( io.remove(folder..variables.SnapShot.FileEraseName..extensionFile) ) then -- Eintrag aus der Tabelle löschen table.remove(variables.SnapShot.Files, value) variables.SnapShot.FileEraseName = "..." variables.SnapShot.FileEraseIndex = 1 -- Letzte Snapshotdatei einstellen if #variables.SnapShot.Files > 1 then variables.SnapShot.FileName = variables.SnapShot.Files[#variables.SnapShot.Files] variables.SnapShot.FileIndex = #variables.SnapShot.Files else variables.SnapShot.FileName = "..." variables.SnapShot.FileIndex = 1 end -- und anzeigen form.reinit(1) end end) -- Neue oder bestehende Daten anzeigen if (variables.SnapShot.FileName:len() > 0) then local file = io.open(folder..variables.SnapShot.FileName..extensionFile, "r") addSpacer(318, 10) if (file) then local line line = io.readline(file) addRow(2) addLabel({label=line, width=280, font=FONT_BOLD}) repeat line = io.readline(file) addRow(2) addLabel({label=line, width=280}) until (not line) io.close(file) end end -- Motorüberwachung ------------------- elseif (se.option == 6) then addSpacer(318, 10) addLabel({label=trans.engineSw, font=FONT_BOLD}) -- Freigabeschalter Motor addRow(2) addLabel({label=trans.switchMotor}) addInputbox(sw.engineSw, true, function(value) if (not isSwitch(value)) then value = nil end sw.engineSw = value end) -- Drosselhebel auswählen addRow(2) addLabel({label=trans.prop}) addInputbox(sw.flightSw, true, function(value) if (not isSwitch(value)) then value = nil end sw.flightSw = value end) -- Schwellwert für Drosselhebel addRow(2) addLabel({label=trans.timeTh, width=230}) addIntbox(se.timeTh, -100, 100, -95, 0, 1, function(value) se.timeTh = value end) -- Alarme einstellen addSpacer(318, 10) addLabel({label=trans.engineMonitoringAlarm, font=FONT_BOLD}) -- Sound bei gesperrtem Motor und Drossel > Schwellwert addRow(2) addLabel({label=trans.sound}) addAudioFilebox(se.monitorSound, function(value) se.monitorSound = value end) -- Vibration bei gesperrtem Motor und Drossel > Schwellwert local vibrateForm addRow(2) addLabel({label=trans.vibrate, width=275}) vibrateForm = addCheckbox(se.vibrate, function(value) se.vibrate = not value form.setValue(vibrateForm, se.vibrate) end) -- Timer Motorzeitverhalten addSpacer(318, 10) addLabel({label=trans.flightSw, font=FONT_BOLD}) -- reset Motor-Timer addRow(2) addLabel({label=trans.TxSensor_TimerBeepResetOffSw}) addInputbox(sw.resetMotorTimerSw, true, function(value) if (not isSwitch(value)) then value = nil end sw.resetMotorTimerSw = value end) -- Zeit bei Senderneustart beibehalten local shortForm addRow(2) addLabel({label=trans.short, width=275}) shortForm = addCheckbox(se.TimerZeitSpeichern, function(value) se.TimerZeitSpeichern = not value form.setValue(shortForm, se.TimerZeitSpeichern) end) elseif (se.option == 7) then --Flüge addSpacer(318, 10) addLabel({label=trans.flights, font=FONT_BOLD}) addRow(3) addLabel({label=trans.resetStatsSw, width=160}) addIntbox(se.flightsReset, 0, 999999, 0, 0, 1, function(value) se.flightsReset = value end) addInputbox(sw.resetStatsSw, true, function(value) if (not isSwitch(value)) then value = nil end sw.resetStatsSw = value end) addRow(3) addLabel({label=trans.statsFlightSw, width=160}) addIntbox(se.TimeDelay, 0, 110, 0, 0, 1, function(value) se.TimeDelay = value end) addInputbox(sw.statsFlightSw, true, function(value) if (not isSwitch(value)) then value = nil end sw.statsFlightSw = value end) addSpacer(318, 10) ------------------ -- Timer / Ansagen ------------------ elseif (se.option == 8) then -- ++++++++++++++++++++++ -- +++++ Timer Beep +++++ -- ++++++++++++++++++++++ addSpacer(318, 10) addLabel({label=trans.TxSensor_TimerBeep, font=FONT_BOLD}) addRow(3) addLabel({label=trans.TxSensor_TimerBeep.." ("..variables.Sensors[variables.TimerBeepIdx].unit..")", width=160}) addIntbox(se.beepMin, 0, 99, 10, 0, 1, function(value) se.beepMin = value timeVars.bTime = nil timeHMS.bMin, timeHMS.bSec = se.beepMin, se.beepSec variables.Sensors[variables.TimerBeepIdx].valSec = timeHMS.cSec variables.Sensors[variables.TimerBeepIdx].valMin = timeHMS.cMin end) addIntbox(se.beepSec, 0, 59, 0, 0, 1, function(value) se.beepSec = value timeVars.bTime = nil timeHMS.bMin, timeHMS.bSec = se.beepMin, se.beepSec variables.Sensors[variables.TimerBeepIdx].valSec = timeHMS.bSec variables.Sensors[variables.TimerBeepIdx].valMin = timeHMS.bMin end) form.addRow(2) addLabel({label=trans.TxSensor_TimerBeepCmdFile, width=180}) addSelectbox(variables.BeepCmd.FileList, variables.BeepCmd.iFileListIdx, true, function(value) variables.BeepCmd.File = variables.BeepCmd.FileList[value] variables.BeepCmd.iFileListIdx = value if (variables.BeepCmd.File ~= "...") then local file = io.readall(folder..variables.BeepCmd.File..extensionJsonFile) variables.Sensors[variables.TimerBeepIdx].TimerBeepCmd = json.decode(file) else variables.Sensors[variables.TimerBeepIdx].TimerBeepCmd = nil end end) addRow(2) addLabel({label=trans.TxSensor_TimerBeepStartSw}) addInputbox(sw.startBeepTimerSw, true, function(value) if (not isSwitch(value)) then value = nil end sw.startBeepTimerSw = value end) addRow(2) addLabel({label=trans.TxSensor_TimerBeepPauseSw}) addInputbox(sw.pauseBeepTimerSw, true, function(value) if (not isSwitch(value)) then value = nil end sw.pauseBeepTimerSw = value end) addRow(2) addLabel({label=trans.TxSensor_TimerBeepResetOffSw}) addInputbox(sw.resetBeepTimerSw, true, function(value) if (not isSwitch(value)) then value = nil end sw.resetBeepTimerSw = value end) -- ++++++++++++++++++++++++++ -- +++++ Timer Flugzeit +++++ -- ++++++++++++++++++++++++++ addSpacer(318, 10) addLabel({label=trans.TxSensor_FlightTimerMenu, font=FONT_BOLD}) addRow(2) addLabel({label=trans.TxSensor_FlightTimerStart}) addInputbox(sw.startFlightTimerSw, true, function(value) if (not isSwitch(value)) then value = nil end sw.startFlightTimerSw = value end) addRow(2) addLabel({label=trans.TxSensor_TimerBeepPauseSw}) addInputbox(sw.pauseFlightTimerSw, true, function(value) if (not isSwitch(value)) then value = nil end sw.pauseFlightTimerSw = value end) addRow(2) addLabel({label=trans.TxSensor_TimerBeepResetOffSw}) addInputbox(sw.resetFlightTimerSw, true, function(value) if (not isSwitch(value)) then value = nil end sw.resetFlightTimerSw = value end) -- Zeit bei Senderneustart beibehalten local shortForm addRow(2) addLabel({label=trans.short, width=275}) shortForm = addCheckbox(se.TimerZeitSpeichern, function(value) se.TimerZeitSpeichern = not value form.setValue(shortForm, se.TimerZeitSpeichern) end) -- +++++++++++++++++++++++++++ -- +++++ Timer Countdown +++++ -- +++++++++++++++++++++++++++ addSpacer(318, 10) addLabel({label=trans.timer, font=FONT_BOLD}) addRow(3) addLabel({label=trans.countdown, width=160}) addIntbox(se.countdownMin, 0, 99, 10, 0, 1, function(value) se.countdownMin = value timeVars.cTime = nil timeHMS.cMin, timeHMS.cSec = se.countdownMin, se.countdownSec variables.Sensors[variables.CountdownTimeIdx].valSec = timeHMS.cSec variables.Sensors[variables.CountdownTimeIdx].valMin = timeHMS.cMin end) addIntbox(se.countdownSec, 0, 59, 0, 0, 1, function(value) se.countdownSec = value timeVars.cTime = nil timeHMS.cMin, timeHMS.cSec = se.countdownMin, se.countdownSec variables.Sensors[variables.CountdownTimeIdx].valSec = timeHMS.cSec variables.Sensors[variables.CountdownTimeIdx].valMin = timeHMS.cMin end) -- Countdown zusätzlicher Startschalter addRow(2) addLabel({label=trans.TxSensor_TimerBeepStartSw}) addInputbox(sw.startCountdownTimerSw, true, function(value) if (not isSwitch(value)) then value = nil end sw.startCountdownTimerSw = value end) addRow(2) addLabel({label=trans.TxSensor_TimerBeepPauseSw}) addInputbox(sw.pauseCountdownTimerSw, true, function(value) if (not isSwitch(value)) then value = nil end sw.pauseCountdownTimerSw = value end) addRow(2) addLabel({label=trans.TxSensor_TimerBeepResetOffSw}) addInputbox(sw.resetCountdownTimerSw, true, function(value) if (not isSwitch(value)) then value = nil end sw.resetCountdownTimerSw = value end) addRow(2) addLabel({label=trans.sou}) addAudioFilebox(se.timerSound, function(value) se.timerSound = value end) local colorForm addRow(2) addLabel({label=trans.color, width=275}) colorForm = addCheckbox(se.color, function(value) se.color = not value form.setValue(colorForm, se.color) end) -- Vibration bei Countdownende local vibratesForm addRow(2) addLabel({label=trans.vibrates, width=275}) vibratesForm = addCheckbox(se.vibrates, function(value) se.vibrates = not value form.setValue(vibratesForm, se.vibrates) end) -- +++++++++++++++++++++++++++++++++ -- +++++ Ansage von Ist-Werten +++++ -- +++++++++++++++++++++++++++++++++ addSpacer(318, 10) addLabel({label=trans.labelAlarmp, font=FONT_BOLD}) -- Timer addRow(2) addLabel({label=trans.an3Sw}) addInputbox(sw.an3Sw, true, function(value) if (not isSwitch(value)) then value = nil end sw.an3Sw = value end) -- Flugzeit addRow(2) addLabel({label=trans.an4Sw}) addInputbox(sw.an4Sw, true, function(value) if (not isSwitch(value)) then value = nil end sw.an4Sw = value end) --Ansage der Ist-Höhe addSpacer(318, 10) addLabel({label=trans.varih, font=FONT_BOLD}) addRow(2) addLabel({label=trans.varihoheSw, width=260}) addInputbox(sw.varihoheSw, true, function(value) if (not isSwitch(value)) then value = nil end sw.varihoheSw = value end) -- Ansage bei ... (Steigen, Sinken oder Beidem) local mitohne = {trans.steigen, trans.sinken, trans.beides} addRow(2) addLabel({label=trans.mitohne, width=200}) addSelectbox(mitohne, se.mitohne, false, function(value) se.mitohne = value end) -- Interval in Meter addRow(2) addLabel({label=trans.gehohe, width=250}) addIntbox(se.gehohe, 1, 600, 50, 0, 1, function(value) se.gehohe = value end) -- Ansage ohne Motor local riseForm addRow(3) addLabel({label=trans.riseEngine, width=160}) addIntbox(se.risea, 1, 99, 5, 0, 1, function(value) se.risea = value end , {width=118}) riseForm = addCheckbox(se.rise, function(value) se.rise = not value form.setValue(riseForm, se.rise) end) -- Auswahltabelle aktualisieren, damit umbennante TeleValues korrekt dargestellt werden. for i=1, ACC_OF_TELEVALUES do local Idx = string.format("iTVInst%d", i) variables.Ans.tabValues[i+1] = TelVal[Idx].sTelValName end variables.Ans.tabValues[ACC_OF_TELEVALUES + 2] = trans.drawBarChart.." 1" variables.Ans.tabValues[ACC_OF_TELEVALUES + 3] = trans.drawBarChart.." 2" -- Datenquelle zuordnen: Höhenwert addRow(2) addLabel({label=trans.menu_AnnouncmentValueHeight, width=230}) addSelectbox(variables.Ans.tabValues, variables.Ans.iValueNoAnsageHoeheMeter, true, function(value) variables.Ans.iValueNoAnsageHoeheMeter = value end) -- Datenquelle zuordnen: Motorstrom addRow(2) addLabel({label=trans.menu_AnnouncmentValueCurrent, width=230}) addSelectbox(variables.Ans.tabValues, variables.Ans.iValueNoAnsageHoeheMotorStrom, true, function(value) variables.Ans.iValueNoAnsageHoeheMotorStrom = value end) elseif (se.option == 9) then --Sensors / Sensoren... und Rücksetzen -- MTAG Sensor zuweisen addSpacer(318, 10) addLabel({label=trans.menu_MTAGSensor, font=FONT_BOLD}) -- Sensor auswählen addRow(2) addLabel({label=trans.menu_MTAGSensorID, width=150}) addSelectbox(TelVal.SensorListLabel, variables.MTAG.iSensorNo, true, function(value) -- Den ausgewählten Sensor zuordnen variables.MTAG.sSensorName = TelVal.SensorListLabel[value] variables.MTAG.iSensorID = TelVal.SensorListId[value] variables.MTAG.iSensorNo = value variables.MTAG.iSensorIdx = TelVal.SensorListIdx[value] variables.MTAG.iSensorType = TelVal.SensorListType[value] end) -- Eingabe der Hintergrundfarbe (Initwert = 0 --> keine Hintergrundfarbe) local sText = trans[string.format("ColName%d", variables.MTAG.iBgColor)].." " local ColNameForm -- Farbnamen anzeigen addRow(1) ColNameForm = addLabel({label=sText, font=FONT_MINI, alignRight=true}) form.addRow(2) addLabel({label=trans.menu_MTAGSensorBgColor, width=260}) addIntbox(variables.MTAG.iBgColor, 0, 44, variables.MTAG.iBgColor, 0, 1, function(value) variables.MTAG.iBgColor = value bShowColorByPrintForm = true changeColorByIndex(value, 255) sText = trans[string.format("ColName%d", value)].." " form.setProperties(ColNameForm,{label=sText}) end) -- GPS Sensor zuweisen addSpacer(318, 10) addLabel({label=trans.menu_GPSSensor, font=FONT_BOLD}) -- Sensor auswählen addRow(2) addLabel({label=trans.menu_GPSSensorID, width=150}) addSelectbox(TelVal.SensorListLabel, variables.GPS.iSensorNo, true, function(value) -- Den ausgewählten Sensor zuordnen variables.GPS.sSensorName = TelVal.SensorListLabel[value] variables.GPS.iSensorID = TelVal.SensorListId[value] variables.GPS.iSensorNo = value variables.GPS.iSensorIdx = TelVal.SensorListIdx[value] variables.GPS.iSensorType = TelVal.SensorListType[value] -- Jetzt werden die derzeit noch eingestellten Sensorwerte zurückgesetzt variables.GPS.sLatParam = "..." variables.GPS.iLatParamNo = 1 -- Index im Sensorwertefeld sensorbezogen variables.GPS.iLatParamIdx = 1 -- Index im kompletten Sensorfeld variables.GPS.sLatEinheit = " ?" variables.GPS.iLatNachkomma = 0 variables.GPS.sLonParam = "..." variables.GPS.iLonParamNo = 1 variables.GPS.iLonParamIdx = 1 variables.GPS.sLonEinheit = " ?" variables.GPS.iLonNachkomma = 1 form.reinit(1) -- Die neu gewählte Sensorwerteliste auch richtig anzeigen end) -- Sensorwert Breite auswählen addRow(2) addLabel({label=trans.menu_GPSSensorValueLat, width=150}) -- Sicherheitsabfrage if(variables.GPS.iSensorNo <= 1)then variables.GPS.iSensorNo = 2 -- muß mindestens 1 sein -> kein Sensor angewählt bSensorListeReset = true else bSensorListeReset = false end -- Hier wird die Parameterliste des ausgewählten Sensors eingestellt local ParameterList, ParameterListIdx ParameterList = string.format("SensorListWertLabel%d", variables.GPS.iSensorNo -1 ) -- Der erste Wert ist der NULL-Wert ParameterListIdx = string.format("SensorListWertLabelIdx%d", variables.GPS.iSensorNo -1 ) -- Den Offset durch den Sensor selbst berücksichtigen addSelectbox( TelVal[ParameterList], variables.GPS.iLatParamNo, true, function(value) if (value == 1) then -- Sensorwert-Parameter zurücksetzen variables.GPS.sLatParam = "..." variables.GPS.iLatParamNo = 1 variables.GPS.iLatParamIdx = 1 variables.GPS.sLatEinheit = " ?" variables.GPS.iLatNachkomma = 0 else -- Den ausgewählten Sensorwert der TelVal-Instanz zuordnen variables.GPS.sLatParam = TelVal[ParameterList][value] variables.GPS.iLatParamNo = value variables.GPS.iLatParamIdx = TelVal[ParameterListIdx][value] -- Externer (Receiver) Sensor variables.GPS.sLatEinheit = TelVal.Sensors[variables.GPS.iLatParamIdx].unit variables.GPS.iLatNachkomma = TelVal.Sensors[variables.GPS.iLatParamIdx].decimals -- Die aktuellen Werte löschen variables.GPS.Laenge = 0 end end) if bSensorListeReset then variables.GPS.iSensorNo = 1 bSensorListeReset = false end -- Sensorwert Länge auswählen addRow(2) addLabel({label=trans.menu_GPSSensorValueLon, width=150}) -- Sicherheitsabfrage if(variables.GPS.iSensorNo <= 1)then variables.GPS.iSensorNo = 2 -- muß mindestens 1 sein -> kein Sensor angewählt bSensorListeReset = true else bSensorListeReset = false end -- Hier wird die Parameterliste des ausgewählten Sensors eingestellt local ParameterList, ParameterListIdx ParameterList = string.format("SensorListWertLabel%d", variables.GPS.iSensorNo -1 ) ParameterListIdx = string.format("SensorListWertLabelIdx%d", variables.GPS.iSensorNo -1 ) -- Den Offset durch den Sensor selbst berücksichtigen addSelectbox( TelVal[ParameterList], variables.GPS.iLonParamNo, true, function(value) if (value == 1) then -- Sensorwert-Parameter zurücksetzen variables.GPS.sLonParam = "..." variables.GPS.iLonParamNo = 1 variables.GPS.iLonParamIdx = 1 variables.GPS.sLonEinheit = " ?" variables.GPS.iLonNachkomma = 1 else -- Den ausgewählten Sensorwert der TelVal-Instanz zuordnen variables.GPS.sLonParam = TelVal[ParameterList][value] variables.GPS.iLonParamNo = value variables.GPS.iLonParamIdx = TelVal[ParameterListIdx][value] -- Externer (Receiver) Sensor variables.GPS.sLonEinheit = TelVal.Sensors[variables.GPS.iLonParamIdx].unit variables.GPS.iLonNachkomma = TelVal.Sensors[variables.GPS.iLonParamIdx].decimals -- Die aktuellen Werte löschen variables.GPS.Laenge = 0 end end) if bSensorListeReset then variables.GPS.iSensorNo = 1 bSensorListeReset = false end -- Eingabe der Hintergrundfarbe (Initwert = 0 --> keine Hintergrundfarbe) local sText = trans[string.format("ColName%d", variables.GPS.iBgColor)].." " local ColNameForm -- Farbnamen anzeigen addRow(1) ColNameForm = addLabel({label=sText, font=FONT_MINI, alignRight=true}) form.addRow(2) addLabel({label=trans.menu_GPSSensorBgColor, width=260}) addIntbox(variables.GPS.iBgColor, 0, 44, variables.GPS.iBgColor, 0, 1, function(value) variables.GPS.iBgColor = value --system.pSave("GPSiBgColor", value) bShowColorByPrintForm = true changeColorByIndex(value, 255) sText = trans[string.format("ColName%d", value)].." " form.setProperties(ColNameForm,{label=sText}) end) --Virtueller Sensor (4 Grundrechenarten) addSpacer(318, 10) addLabel({label=trans.TxSensor_MathHeadline, font=FONT_BOLD}) -- Sensor A auswählen addRow(2) addLabel({label=trans.TxSensor_MathSensorA, width=150}) addSelectbox(TelVal.SensorListLabel, variables.ViS.iSensorNoA, true, function(value) variables.ViS.iOperation = 0 -- Berechnung unmittelbar abschalten --system.pSave("ViSiOperation", variables.ViS.iOperation) -- Den ausgewählten Sensor zuordnen variables.ViS.sSensorNameA = TelVal.SensorListLabel[value] variables.ViS.iSensorIDA = TelVal.SensorListId[value] variables.ViS.iSensorNoA = value variables.ViS.iSensorIdxA = TelVal.SensorListIdx[value] variables.ViS.iSensorTypeA = TelVal.SensorListType[value] -- Jetzt werden die derzeit noch eingestellten Sensorwerte zurückgesetzt variables.ViS.sParamA = "..." variables.ViS.iParamNoA = 1 -- Index im Sensorwertefeld sensorbezogen variables.ViS.iParamIdxA = 1 -- Index im kompletten Sensorfeld variables.ViS.sEinheitA = " ?" variables.ViS.iNachkommaA = 0 form.reinit(1) -- Die neu gewählte Sensorwerteliste auch richtig anzeigen end) -- Sensorwert A auswählen addRow(2) addLabel({label=trans.TxSensor_MathSensorWertA, width=150}) -- Sicherheitsabfrage if(variables.ViS.iSensorNoA <= 1)then variables.ViS.iSensorNoA = 2 -- muß mindestens 1 sein -> kein Sensor angewählt bSensorListeReset = true else bSensorListeReset = false end -- Hier wird die Parameterliste des ausgewählten Sensors eingestellt ParameterList = string.format("SensorListWertLabel%d", variables.ViS.iSensorNoA -1 ) ParameterListIdx = string.format("SensorListWertLabelIdx%d", variables.ViS.iSensorNoA -1 ) -- Den Offset durch den Sensor selbst berücksichtigen addSelectbox( TelVal[ParameterList], variables.ViS.iParamNoA, true, function(value) variables.ViS.iOperation = 0 if (value == 1) then -- Sensorwert-Parameter zurücksetzen variables.ViS.sParamA = "..." variables.ViS.iParamNoA = 1 variables.ViS.iParamIdxA = 1 variables.ViS.sEinheitA = " ?" variables.ViS.iNachkommaA = 0 else -- Den ausgewählten Sensorwert zuordnen variables.ViS.sParamA = TelVal[ParameterList][value] variables.ViS.iParamNoA = value variables.ViS.iParamIdxA = TelVal[ParameterListIdx][value] if (variables.ViS.iSensorTypeA == 2) then -- Interner / Sender Sensor variables.ViS.sEinheitA = variables.Sensors[variables.ViS.iParamIdxA].unit variables.ViS.iNachkommaA = variables.Sensors[variables.ViS.iParamIdxA].decimals else -- Externer (Receiver) Sensor variables.ViS.sEinheitA = TelVal.Sensors[variables.ViS.iParamIdxA].unit variables.ViS.iNachkommaA = TelVal.Sensors[variables.ViS.iParamIdxA].decimals end end form.reinit(1) -- Die neu gewählte Sensorwerteliste auch richtig anzeigen end) if bSensorListeReset then variables.ViS.iSensorNoA = 1 bSensorListeReset = false end -- Sensor B auswählen addRow(2) addLabel({label=trans.TxSensor_MathSensorB, width=150}) addSelectbox(TelVal.SensorListLabel, variables.ViS.iSensorNoB, true, function(value) variables.ViS.iOperation = 0 -- Den ausgewählten Sensor zuordnen variables.ViS.sSensorNameB = TelVal.SensorListLabel[value] variables.ViS.iSensorIDB = TelVal.SensorListId[value] variables.ViS.iSensorNoB = value variables.ViS.iSensorIdxB = TelVal.SensorListIdx[value] variables.ViS.iSensorTypeB = TelVal.SensorListType[value] -- Jetzt werden die derzeit noch eingestellten Sensorwerte zurückgesetzt variables.ViS.sParamB = "..." variables.ViS.iParamNoB = 1 -- Index im Sensorwertefeld sensorbezogen variables.ViS.iParamIdxB = 1 -- Index im kompletten Sensorfeld variables.ViS.sEinheitB = " ?" variables.ViS.iNachkommaB = 0 form.reinit(1) -- Die neu gewählte Sensorwerteliste auch richtig anzeigen end) -- Sensorwert B auswählen addRow(2) addLabel({label=trans.TxSensor_MathSensorWertB, width=150}) -- Sicherheitsabfrage if(variables.ViS.iSensorNoB <= 1)then variables.ViS.iSensorNoB = 2 -- muß mindestens 1 sein -> kein Sensor angewählt bSensorListeReset = true else bSensorListeReset = false end -- Hier wird die Parameterliste des ausgewählten Sensors eingestellt ParameterList = string.format("SensorListWertLabel%d", variables.ViS.iSensorNoB -1 ) ParameterListIdx = string.format("SensorListWertLabelIdx%d", variables.ViS.iSensorNoB -1 ) -- Den Offset durch den Sensor selbst berücksichtigen addSelectbox( TelVal[ParameterList], variables.ViS.iParamNoB, true, function(value) variables.ViS.iOperation = 0 if (value == 1) then -- Sensorwert-Parameter zurücksetzen variables.ViS.sParamB = "..." variables.ViS.iParamNoB = 1 variables.ViS.iParamIdxB = 1 variables.ViS.sEinheitB = " ?" variables.ViS.iNachkommaB = 0 else -- Den ausgewählten Sensorwert zuordnen variables.ViS.sParamB = TelVal[ParameterList][value] variables.ViS.iParamNoB = value variables.ViS.iParamIdxB = TelVal[ParameterListIdx][value] if (variables.ViS.iSensorTypeB == 2) then -- Interner / Sender Sensor variables.ViS.sEinheitB = variables.Sensors[variables.ViS.iParamIdxB].unit variables.ViS.iNachkommaB = variables.Sensors[variables.ViS.iParamIdxB].decimals else -- Externer (Receiver) Sensor variables.ViS.sEinheitB = TelVal.Sensors[variables.ViS.iParamIdxB].unit variables.ViS.iNachkommaB = TelVal.Sensors[variables.ViS.iParamIdxB].decimals end end form.reinit(1) -- Die neu gewählte Sensorwerteliste auch richtig anzeigen end) if bSensorListeReset then variables.ViS.iSensorNoB = 1 bSensorListeReset = false end -- Grundrechenart einstellen addRow(2) addLabel({label=trans.TxSensor_MathOperation, width=270, font=FONT_BOLD}) local bOpForm1, bOpForm2, bOpForm3, bOpForm4 local start addRow(2) addLabel({label=trans.TxSensor_MathOperation1, width=270}) if(variables.ViS.iOperation == 1) then start = true else start = false end bOpForm1 = addCheckbox(start, function(value) form.setValue(bOpForm1, not value) if value then -- aus variables.ViS.iOperation = 0 else -- ein variables.ViS.iOperation = 1 variables.ViS.unit = variables.ViS.sEinheitA.."*"..variables.ViS.sEinheitB variables.Sensors[variables.TxVirtualSensor].unit = variables.ViS.unit end form.reinit(1) end) addRow(2) addLabel({label=trans.TxSensor_MathOperation2, width=270}) if(variables.ViS.iOperation == 2) then start = true else start = false end bOpForm2 = addCheckbox(start, function(value) form.setValue(bOpForm2, not value) if value then -- aus variables.ViS.iOperation = 0 else -- ein variables.ViS.iOperation = 2 variables.ViS.unit = variables.ViS.sEinheitA.."/"..variables.ViS.sEinheitB variables.Sensors[variables.TxVirtualSensor].unit = variables.ViS.unit end form.reinit(1) end) addRow(2) addLabel({label=trans.TxSensor_MathOperation3, width=270}) if(variables.ViS.iOperation == 3) then start = true else start = false end bOpForm3 = addCheckbox(start, function(value) form.setValue(bOpForm3, not value) if value then -- aus variables.ViS.iOperation = 0 else -- ein variables.ViS.iOperation = 3 variables.ViS.unit = variables.ViS.sEinheitA variables.Sensors[variables.TxVirtualSensor].unit = variables.ViS.unit end form.reinit(1) end) addRow(2) addLabel({label=trans.TxSensor_MathOperation4, width=270}) if(variables.ViS.iOperation == 4) then start = true else start = false end bOpForm4 = addCheckbox(start, function(value) form.setValue(bOpForm4, not value) if value then -- aus variables.ViS.iOperation = 0 else -- ein variables.ViS.iOperation = 4 variables.ViS.unit = variables.ViS.sEinheitA variables.Sensors[variables.TxVirtualSensor].unit = variables.ViS.unit end form.reinit(1) end) --Reset von Werten addSpacer(318, 10) addLabel({label=trans.reset, font=FONT_BOLD}) addRow(2) addLabel({label=trans.resetRxSw}) addInputbox(sw.resetRxSw, true, function(value) if (not isSwitch(value)) then value = nil end sw.resetRxSw = value end) addRow(2) addLabel({label=trans.resetTeleSw}) addInputbox(sw.resetTeleSw, true, function(value) if (not isSwitch(value)) then value = nil end sw.resetTeleSw = value end) --------------------------------- -- Empfängerüberwachung -- REX -- --------------------------------- elseif (se.option == 10) then -- addSpacer(318, 10) -- addLabel({label=trans.menu_Rex_Control, font=FONT_BOLD}) addRow(2) addLabel({label=trans.menu_Rex_ModelTyp, width=160}) addSelectbox(variables.Rex.TypList, variables.Rex.Selected.Index, true, function(value) variables.Rex.Selected.Index = value -- Voreingestellte Daten übertragen variables.Rex.Selected.Qlimit = variables.Rex.Para[value].Qlimit -- Grenzwert in % variables.Rex.Selected.Qtime = variables.Rex.Para[value].Qtime -- Verzögerungszeit in ms variables.Rex.Selected.A1limit = variables.Rex.Para[value].A1limit -- Wert 0 - 9 variables.Rex.Selected.A1time = variables.Rex.Para[value].A1time -- Verzögerungszeit in ms variables.Rex.Selected.A2limit = variables.Rex.Para[value].A2limit -- Wert 0 - 9 variables.Rex.Selected.A2time = variables.Rex.Para[value].A2time -- Verzögerungszeit in ms form.reinit(1) end) addSpacer(318, 10) addLabel({label=trans.menu_Rex_GrenzenVerzoegerung, font=FONT_BOLD}) -- Q-Parameter form.addRow(2) addLabel({label=trans.menu_Rex_QLimit, width=210}) addIntbox(variables.Rex.Selected.Qlimit, 0, 99, variables.Rex.Selected.Qlimit, 0, 1, function(value) variables.Rex.Selected.Qlimit = value end,{label=" %"}) form.addRow(2) addLabel({label=trans.menu_Rex_QTime, width=210}) addIntbox(variables.Rex.Selected.Qtime, 0, 10000, variables.Rex.Selected.Qtime, 0, 100, function(value) variables.Rex.Selected.Qtime = value end,{label=" ms"}) -- A1-Parameter form.addRow(2) addLabel({label=trans.menu_Rex_A1Limit, width=210}) addIntbox(variables.Rex.Selected.A1limit, 0, 9, variables.Rex.Selected.A1limit, 0, 1, function(value) variables.Rex.Selected.A1limit = value end) form.addRow(2) addLabel({label=trans.menu_Rex_A1Time, width=210}) addIntbox(variables.Rex.Selected.A1time, 0, 10000, variables.Rex.Selected.A1time, 0, 100, function(value) variables.Rex.Selected.A1time = value end,{label=" ms"}) -- A2-Parameter form.addRow(2) addLabel({label=trans.menu_Rex_A2Limit, width=210}) addIntbox(variables.Rex.Selected.A2limit, 0, 9, variables.Rex.Selected.A2limit, 0, 1, function(value) variables.Rex.Selected.A2limit = value end) form.addRow(2) addLabel({label=trans.menu_Rex_A2Time, width=210}) addIntbox(variables.Rex.Selected.A2time, 0, 10000, variables.Rex.Selected.A2time, 0, 100, function(value) variables.Rex.Selected.A2time = value end,{label=" ms"}) -- Eingabe der Sounds --------------------- -- Sounddateien addSpacer(318, 10) addLabel({label=trans.menu_Rex_Sound, font=FONT_BOLD}) addRow(2) addLabel({label=trans.menu_Rex_SoundQ}) addAudioFilebox(variables.Rex.Selected.SoundQ, function(value) variables.Rex.Selected.SoundQ = value end) addRow(2) addLabel({label=trans.menu_Rex_SoundA1}) addAudioFilebox(variables.Rex.Selected.SoundA1, function(value) variables.Rex.Selected.SoundA1 = value end) addRow(2) addLabel({label=trans.menu_Rex_SoundA2}) addAudioFilebox(variables.Rex.Selected.SoundA2, function(value) variables.Rex.Selected.SoundA2 = value end) addRow(2) addLabel({label=trans.menu_Rex_SoundA1A2}) addAudioFilebox(variables.Rex.Selected.SoundA1A2, function(value) variables.Rex.Selected.SoundA1A2 = value end) -- Eingabe der Farben --------------------- -- Farbvariablen für die Receiverkacheln addSpacer(318, 10) addLabel({label=trans.menu_Rex_Receiver, font=FONT_BOLD}) -- Aktiv Hintergrund local sText = trans[string.format("ColName%d", variables.Rex.Selected.bgColorON)] local ColNameForm3 form.addRow(2) ColNameForm3 = addLabel({label=trans.menu_Rex_RecbgColorON.." ("..sText..")", width=260}) addIntbox(variables.Rex.Selected.bgColorON, 0, 44, variables.Rex.Selected.bgColorON, 0, 1, function(value) bShowColorByPrintForm = true changeColorByIndex(value, 255) variables.Rex.Selected.bgColorON = value sText = trans[string.format("ColName%d", value)] form.setProperties(ColNameForm3,{label=trans.menu_Rex_RecbgColorON.." ("..sText..")"}) end) -- Inaktiv Hintergrund sText = trans[string.format("ColName%d", variables.Rex.Selected.bgColorOFF)] local ColNameForm4 form.addRow(2) ColNameForm4 =addLabel({label=trans.menu_Rex_RecbgColorOFF.." ("..sText..")", width=260}) addIntbox(variables.Rex.Selected.bgColorOFF, 0, 44, variables.Rex.Selected.bgColorOFF, 0, 1, function(value) bShowColorByPrintForm = true changeColorByIndex(value, 255) variables.Rex.Selected.bgColorOFF = value sText = trans[string.format("ColName%d", value)] form.setProperties(ColNameForm4,{label=trans.menu_Rex_RecbgColorOFF.." ("..sText..")"}) end) -- Aktiv Normaltext sText = trans[string.format("ColName%d", variables.Rex.Selected.txColorON)] local ColNameForm1 form.addRow(2) ColNameForm1 = addLabel({label=trans.menu_Rex_RectxColorON.." ("..sText..")", width=260}) addIntbox(variables.Rex.Selected.txColorON, 0, 44, variables.Rex.Selected.txColorON, 0, 1, function(value) bShowColorByPrintForm = true changeColorByIndex(value, 255) variables.Rex.Selected.txColorON = value sText = trans[string.format("ColName%d", value)] form.setProperties(ColNameForm1,{label=trans.menu_Rex_RectxColorON.." ("..sText..")"}) end) -- Inaktiv Normaltext sText = trans[string.format("ColName%d", variables.Rex.Selected.txColorOFF)] local ColNameForm2 form.addRow(2) ColNameForm2 = addLabel({label=trans.menu_Rex_RectxColorOFF.." ("..sText..")", width=260}) addIntbox(variables.Rex.Selected.txColorOFF, 0, 44, variables.Rex.Selected.txColorOFF, 0, 1, function(value) bShowColorByPrintForm = true changeColorByIndex(value, 255) variables.Rex.Selected.txColorOFF = value sText = trans[string.format("ColName%d", value)] form.setProperties(ColNameForm2,{label=trans.menu_Rex_RectxColorOFF.." ("..sText..")"}) end) -- Aktiv Überwachungstext sText = trans[string.format("ColName%d", variables.Rex.Selected.txColorONerror)] local ColNameForm5 form.addRow(2) ColNameForm5 = addLabel({label=trans.menu_Rex_RectxColorONerror.." ("..sText..")", width=260}) addIntbox(variables.Rex.Selected.txColorONerror, 0, 44, variables.Rex.Selected.txColorONerror, 0, 1, function(value) bShowColorByPrintForm = true changeColorByIndex(value, 255) variables.Rex.Selected.txColorONerror = value sText = trans[string.format("ColName%d", value)] form.setProperties(ColNameForm5,{label=trans.menu_Rex_RectxColorONerror.." ("..sText..")"}) end) -- Wird derzeit nicht benötigt --[[ -- Inaktiv Überwachungstext sText = trans[string.format("ColName%d", variables.Rex.Selected.txColorOFFerror)] local ColNameForm6 form.addRow(2) ColNameForm6 = addLabel({label=trans.menu_Rex_RectxColorOFFerror.." ("..sText..")", width=260}) addIntbox(variables.Rex.Selected.txColorOFFerror, 0, 44, variables.Rex.Selected.txColorOFFerror, 0, 1, function(value) bShowColorByPrintForm = true changeColorByIndex(value, 255) variables.Rex.Selected.txColorOFFerror = value sText = trans[string.format("ColName%d", value)] form.setProperties(ColNameForm6,{label=trans.menu_Rex_RectxColorOFFerror.." ("..sText..")"}) end) --]] ----------------- -- Oszilloskop -- ----------------- elseif (se.option == 11) then bShowColorByPrintForm = true changeColorByIndex(Oszi.Graph.BgCol, 255) addSpacer(318, 10) addLabel({label=trans.menu_OsziControl, font=FONT_BOLD}) -- Abtastrate einstellen addRow(2) addLabel({label=trans.menu_OsziControlAbtastrate, width=200}) addIntbox(Oszi.Data.Values.T, 100, 2000, 0, 0, 100, function(value) Oszi.Data.Values.T = value ResetOsziData() end,{label=" ms"}) -- Zeitdauer einstellen addRow(2) addLabel({label=trans.menu_OsziControlDauer, width=200}) addIntbox((Oszi.Data.Values.maxTime/1000), 10, 100, 0, 0, 1, function(value) Oszi.Data.Values.maxTime = value * 1000 ResetOsziData() end,{label=" sec"}) addSpacer(318, 10) addLabel({label=trans.menu_OsziControlStartStop, font=FONT_BOLD}) -- Startschalter addRow(2) addLabel({label=trans.menu_OsziControlStart}) addInputbox(sw.OsziStartSw, true, function(value) if (not isSwitch(value)) then value = nil end sw.OsziStartSw = value end) -- Stoppschalter addRow(2) addLabel({label=trans.menu_OsziControlStopp}) addInputbox(sw.OsziStoppSw, true, function(value) if (not isSwitch(value)) then value = nil end sw.OsziStoppSw = value end) -- Resetschalter addRow(2) addLabel({label=trans.menu_OsziControlReset}) addInputbox(sw.OsziResetSw, true, function(value) if (not isSwitch(value)) then value = nil end sw.OsziResetSw = value end) -- OneShot-Schalter addRow(2) addLabel({label=trans.menu_OsziControlOneShot}) addInputbox(sw.OsziOneShotSw, true, function(value) if (not isSwitch(value)) then value = nil end sw.OsziOneShotSw = value end) -- Saveschalter addRow(2) addLabel({label=trans.menu_OsziControlSave}) addInputbox(sw.OsziSaveSw, true, function(value) if (not isSwitch(value)) then value = nil end sw.OsziSaveSw = value end) -- Loadschalter addRow(2) addLabel({label=trans.menu_OsziControlLoad}) addInputbox(sw.OsziLoadSw, true, function(value) if (not isSwitch(value)) then value = nil end sw.OsziLoadSw = value end) addSpacer(318, 10) addLabel({label=trans.menu_OsziData, font=FONT_BOLD}) local temp -- Datenquelle für Kanal 1 addRow(2) addLabel({label=trans.menu_OsziChannel.." 1 "..trans.menu_OsziDataTV, width=200}) if Oszi.Data.Values.Ch1.TVpointer == nil then temp = 1 else temp = Oszi.Data.Values.Ch1.TVpointer + 1 end addSelectbox(Oszi.TVlist, temp, true, function(value) if value == 1 then Oszi.Data.Values.Ch1.TVpointer = nil else Oszi.Data.Values.Ch1.TVpointer = value - 1 -- Weitere Daten aus dem TeleValue übernehmen ID = string.format("iTVInst%d", Oszi.Data.Values.Ch1.TVpointer) Oszi.Data.Values.Ch1.LnCol = TelVal[ID].iTelValBgColor Oszi.Data.Values.Ch1.Header = TelVal[ID].sTelValHeader Oszi.Data.Values.Ch1.Unit = TelVal[ID].sTelValEinheit ResetOsziData() end form.reinit(1) end) -- Maximalwert für Kanal 1 if Oszi.Data.Values.Ch1.TVpointer ~= nil then ID = string.format("iTVInst%d", Oszi.Data.Values.Ch1.TVpointer) addRow(2) addLabel({label=trans.menu_OsziDataMax.."1", width=200}) addIntbox(Oszi.Data.Values.Ch1.maxValue, 1, 100000, 0, 0, 1, function(value) Oszi.Data.Values.Ch1.maxValue = value ResetOsziData() end,{label=" "..TelVal[ID].sTelValEinheit}) end -- Datenquelle für Kanal 2 addRow(2) addLabel({label=trans.menu_OsziChannel.." 2 "..trans.menu_OsziDataTV, width=200}) if Oszi.Data.Values.Ch2.TVpointer == nil then temp = 1 else temp = Oszi.Data.Values.Ch2.TVpointer + 1 end addSelectbox(Oszi.TVlist, temp, true, function(value) if value == 1 then Oszi.Data.Values.Ch2.TVpointer = nil else Oszi.Data.Values.Ch2.TVpointer = value - 1 -- Weitere Daten aus dem TeleValue übernehmen ID = string.format("iTVInst%d", Oszi.Data.Values.Ch2.TVpointer) Oszi.Data.Values.Ch2.LnCol = TelVal[ID].iTelValBgColor Oszi.Data.Values.Ch2.Header = TelVal[ID].sTelValHeader Oszi.Data.Values.Ch2.Unit = TelVal[ID].sTelValEinheit ResetOsziData() end form.reinit(1) end) -- Maximalwert für Kanal 2 if Oszi.Data.Values.Ch2.TVpointer ~= nil then ID = string.format("iTVInst%d", Oszi.Data.Values.Ch2.TVpointer) addRow(2) addLabel({label=trans.menu_OsziDataMax.."2", width=200}) addIntbox(Oszi.Data.Values.Ch2.maxValue, 1, 100000, 0, 0, 1, function(value) Oszi.Data.Values.Ch2.maxValue = value ResetOsziData() end,{label=" "..TelVal[ID].sTelValEinheit}) end -- Datenquelle für Kanal 3 addRow(2) addLabel({label=trans.menu_OsziChannel.." 3 "..trans.menu_OsziDataTV, width=200}) if Oszi.Data.Values.Ch3.TVpointer == nil then temp = 1 else temp = Oszi.Data.Values.Ch3.TVpointer + 1 end addSelectbox(Oszi.TVlist, temp, true, function(value) if value == 1 then Oszi.Data.Values.Ch3.TVpointer = nil else Oszi.Data.Values.Ch3.TVpointer = value - 1 -- Weitere Daten aus dem TeleValue übernehmen ID = string.format("iTVInst%d", Oszi.Data.Values.Ch3.TVpointer) Oszi.Data.Values.Ch3.LnCol = TelVal[ID].iTelValBgColor Oszi.Data.Values.Ch3.Header = TelVal[ID].sTelValHeader Oszi.Data.Values.Ch3.Unit = TelVal[ID].sTelValEinheit ResetOsziData() end form.reinit(1) end) -- Maximalwert für Kanal 3 if Oszi.Data.Values.Ch3.TVpointer ~= nil then ID = string.format("iTVInst%d", Oszi.Data.Values.Ch3.TVpointer) addRow(2) addLabel({label=trans.menu_OsziDataMax.."3", width=200}) addIntbox(Oszi.Data.Values.Ch3.maxValue, 1, 100000, 0, 0, 1, function(value) Oszi.Data.Values.Ch3.maxValue = value ResetOsziData() end,{label=" "..TelVal[ID].sTelValEinheit}) end -- Datenquelle für Kanal 4 addRow(2) addLabel({label=trans.menu_OsziChannel.." 4 "..trans.menu_OsziDataTV, width=200}) if Oszi.Data.Values.Ch4.TVpointer == nil then temp = 1 else temp = Oszi.Data.Values.Ch4.TVpointer + 1 end addSelectbox(Oszi.TVlist, temp, true, function(value) if value == 1 then Oszi.Data.Values.Ch4.TVpointer = nil else Oszi.Data.Values.Ch4.TVpointer = value - 1 -- Weitere Daten aus dem TeleValue übernehmen ID = string.format("iTVInst%d", Oszi.Data.Values.Ch4.TVpointer) Oszi.Data.Values.Ch4.LnCol = TelVal[ID].iTelValBgColor Oszi.Data.Values.Ch4.Header = TelVal[ID].sTelValHeader Oszi.Data.Values.Ch4.Unit = TelVal[ID].sTelValEinheit ResetOsziData() end form.reinit(1) end) -- Maximalwert für Kanal 4 if Oszi.Data.Values.Ch4.TVpointer ~= nil then ID = string.format("iTVInst%d", Oszi.Data.Values.Ch4.TVpointer) addRow(2) addLabel({label=trans.menu_OsziDataMax.."4", width=200}) addIntbox(Oszi.Data.Values.Ch4.maxValue, 1, 100000, 0, 0, 1, function(value) Oszi.Data.Values.Ch4.maxValue = value ResetOsziData() end,{label=" "..TelVal[ID].sTelValEinheit}) end -- Formatierungen der Darstellungen addSpacer(318, 10) addLabel({label=trans.menu_OsziFormat, font=FONT_BOLD}) -- Position der X-Achse festlegen local PosListe = {} PosListe[1] = trans.menu_OsziFormatXaxisPosTop PosListe[2] = trans.menu_OsziFormatXaxisPosCenter PosListe[3] = trans.menu_OsziFormatXaxisPosBottom -- Position der X-Achse addRow(2) addLabel({label=trans.menu_OsziFormatXaxisPos, width=200}) addSelectbox(PosListe, Oszi.Graph.posXaxis, true, function(value) Oszi.Graph.posXaxis = value ResetOsziData() end) -- Gitter einblenden local GitterForm addRow(2) addLabel({label=trans.menu_OsziFormatGitter, width=275}) GitterForm = addCheckbox(Oszi.Graph.Legend.Gitter, function(value) Oszi.Graph.Legend.Gitter = not value form.setValue(GitterForm, Oszi.Graph.Legend.Gitter) end) -- Kachelhöhe addRow(2) addLabel({label=trans.menu_OsziFormatHeight.."50 - 200 Pixel)", width=240}) addIntbox(Oszi.Graph.Height, 50, 200, Oszi.Graph.Height, 0, 1, function(value) Oszi.Graph.Height = value end) -- Eingabe der Hintergrundfarbe (Initwert = 0 --> keine Hintergrundfarbe) local sText = trans[string.format("ColName%d", Oszi.Graph.BgCol)].." " local ColNameForm -- Farbnamen anzeigen addRow(1) ColNameForm = addLabel({label=sText, font=FONT_MINI, alignRight=true}) form.addRow(2) addLabel({label=trans.menu_TelValBgColor, width=260}) addIntbox(Oszi.Graph.BgCol, 0, 44, Oszi.Graph.BgCol, 0, 1, function(value) Oszi.Graph.BgCol = value bShowColorByPrintForm = true changeColorByIndex(value, 255) sText = trans[string.format("ColName%d", value)].." " form.setProperties(ColNameForm,{label=sText}) end) elseif (se.option == 12) then --Expert / Diverses... addLabel({label=trans.vorflug, font=FONT_BOLD}) addRow(2) addLabel({label=trans.vorflugvolt, width=198}) if type(se.vorflugvolt) == "string" then if se.vorflugvolt == "" then se.vorflugvolt = "0" end se.vorflugvolt = tonumber(se.vorflugvolt) end if se.vorflugvolt == nil then se.vorflugvolt = 0 end addIntbox(se.vorflugvolt, 0, 840, 410, 1, 1, function(value) se.vorflugvolt = value end,{label="V"}) -- Sensor auswählen addRow(2) addLabel({label=trans.vorflugSensor, width=150}) addSelectbox(TelVal.SensorListLabel, variables.Vor.iSensorNo, true, function(value) variables.Vor.iOperation = 0 -- Berechnung unmittelbar abschalten -- Den ausgewählten Sensor zuordnen variables.Vor.sSensorName = TelVal.SensorListLabel[value] variables.Vor.iSensorID = TelVal.SensorListId[value] variables.Vor.iSensorNo = value variables.Vor.iSensorIdx = TelVal.SensorListIdx[value] variables.Vor.iSensorType = TelVal.SensorListType[value] -- Jetzt werden die derzeit noch eingestellten Sensorwerte zurückgesetzt variables.Vor.sParam = "..." variables.Vor.iParamNo = 1 -- Index im Sensorwertefeld sensorbezogen variables.Vor.iParamIdx = 1 -- Index im kompletten Sensorfeld variables.Vor.sEinheit = " ?" variables.Vor.iNachkomma = 0 form.reinit(1) -- Die neu gewählte Sensorwerteliste auch richtig anzeigen end) -- Sensorparameter Spannung auswählen addRow(2) addLabel({label=trans.vorflugParameter, width=150}) -- Sicherheitsabfrage if(variables.Vor.iSensorNo <= 1)then variables.Vor.iSensorNo = 2 -- muß mindestens 1 sein -> kein Sensor angewählt bSensorListeReset = true else bSensorListeReset = false end -- Hier wird die Parameterliste des ausgewählten Sensors eingestellt ParameterList = string.format("SensorListWertLabel%d", variables.Vor.iSensorNo -1 ) ParameterListIdx = string.format("SensorListWertLabelIdx%d", variables.Vor.iSensorNo -1 ) -- Den Offset durch den Sensor selbst berücksichtigen addSelectbox( TelVal[ParameterList], variables.Vor.iParamNo, true, function(value) variables.Vor.iOperation = 0 if (value == 1) then -- Sensorwert-Parameter zurücksetzen variables.Vor.sParam = "..." variables.Vor.iParamNo = 1 variables.Vor.iParamIdx = 1 variables.Vor.sEinheit = " ?" variables.Vor.iNachkomma = 0 else -- Den ausgewählten Sensorwert zuordnen variables.Vor.sParam = TelVal[ParameterList][value] variables.Vor.iParamNo = value variables.Vor.iParamIdx = TelVal[ParameterListIdx][value] if (variables.Vor.iSensorType == 2) then -- Interner / Sender Sensor variables.Vor.sEinheit = variables.Sensors[variables.Vor.iParamIdx].unit variables.Vor.iNachkomma = variables.Sensors[variables.Vor.iParamIdx].decimals else -- Externer (Receiver) Sensor variables.Vor.sEinheit = TelVal.Sensors[variables.Vor.iParamIdx].unit variables.Vor.iNachkomma = TelVal.Sensors[variables.Vor.iParamIdx].decimals end end form.reinit(1) -- Die neu gewählte Sensorwerteliste auch richtig anzeigen end) if bSensorListeReset then variables.Vor.iSensorNo = 1 bSensorListeReset = false end -- Modellnamen ansagen addSpacer(318, 10) addLabel({label=trans.modellnameHeader, font=FONT_BOLD}) -- Sounddatei form.addRow(2) addLabel({label=trans.modellnameVoice, width=220}) addAudioFilebox(se.alarmVoice4, function(value) se.alarmVoice4 = value end) -- Zeitverzögerung nach Start addRow(2) addLabel({label=trans.modellname, width=260}) addIntbox(se.modellname, 0, 60, 0, 0, 1, function(value) se.modellname = value end) -- Fenster wechseln addSpacer(318, 10) addLabel({label=trans.switchTilesHeader, font=FONT_BOLD}) -- Geber definieren addRow(2) addLabel({label=trans.switchTiles, width=230}) addInputbox(sw.switchTilesSw, true, function(value) if (not isSwitch(value)) then value = nil end sw.switchTilesSw = value end) -- Alle Sensoren abkoppeln, damit neue Sensoren aufgenommen werden können. -- Sich dadurch ergebene Verschiebungen können so indirekt abgefangen werden. addSpacer(318, 10) local SpezForm addRow(2) addLabel({label=trans.SpezialSensOFF, width=275, font=FONT_BOLD}) SpezForm = addCheckbox(variables.bSpezialSensorenDetach, function(value) variables.bSpezialSensorenDetach = not value form.setValue(SpezForm, variables.bSpezialSensorenDetach) if variables.bSpezialSensorenDetach then -- Jetzt werden alle Sensoreintrgäge in den Televalues, FlexPis, Säulendiagramm, MTAG, GPS und Vorflug abgekoppelt. -- Das beugt einem Absturz bei Entfernen oder Hinzufügen von Sensoren oder angekoppelten Apps vor. -- Alle TeleValues entkoppeln local Idx, sTelValVar for i=1, ACC_OF_TELEVALUES do -- Entkoppeln Idx = string.format("iTVInst%d", i) TelVal[Idx].sTelValSensor = "..." TelVal[Idx].iTelValSensorID = 0 TelVal[Idx].iTelValSensorNo = 1 TelVal[Idx].iTelValSensorIdx = 1 TelVal[Idx].iTelValSensorType = 1 -- Liste der Sensortypen: 1=Empfängersensor; 2=Sendersensor (Calca-App, Timer, Zähler, etc.) TelVal[Idx].bTelValSensorNoName = false -- false = Sensor hat einen Namen TelVal[Idx].sTelValParam = "..." TelVal[Idx].iTelValParamNo = 1 -- Index im Sensorwertefeld sensorbezogen TelVal[Idx].iTelValParamIdx = 1 end -- Säulendiagramm1 entkoppeln SpecTiles.AkkuTank.sSensorName1 = "..." SpecTiles.AkkuTank.iSensorNo1 = 1 SpecTiles.AkkuTank.iSensorId1 = 0 SpecTiles.AkkuTank.iSensorType1 = 1 SpecTiles.AkkuTank.sSensorValueName1 = "..." SpecTiles.AkkuTank.iSensorValueNo1 = 1 SpecTiles.AkkuTank.iSensorValueIdx1 = 1 -- Säulendiagramm2 entkoppeln SpecTiles.AkkuTank.sSensorName2 = "..." SpecTiles.AkkuTank.iSensorNo2 = 1 SpecTiles.AkkuTank.iSensorId2 = 0 SpecTiles.AkkuTank.iSensorType2 = 1 SpecTiles.AkkuTank.sSensorValueName2 = "..." SpecTiles.AkkuTank.iSensorValueNo2 = 1 SpecTiles.AkkuTank.iSensorValueIdx2 = 1 -- MTAG entkoppeln variables.MTAG.sSensorName = "..." variables.MTAG.iSensorNo = 1 variables.MTAG.iSensorID = 0 variables.MTAG.iSensorIdx = 1 variables.MTAG.iSensorType = 1 -- GPS entkoppeln variables.GPS.sSensorName = "..." variables.GPS.iSensorNo = 1 variables.GPS.iSensorID = 0 variables.GPS.iSensorIdx = 1 variables.GPS.iSensorType = 1 variables.GPS.sLatParam = "..." variables.GPS.iLatParamNo = 1 variables.GPS.iLatParamIdx = 1 variables.GPS.sLonParam = "..." variables.GPS.iLonParamNo = 1 variables.GPS.iLonParamIdx = 1 -- Virtellen Sensor entkoppeln variables.ViS.sSensorNameA = "..." variables.ViS.iSensorNoA = 1 variables.ViS.iSensorIDA = 0 variables.ViS.iSensorIdxA = 1 variables.ViS.iSensorTypeA = 1 variables.ViS.sParamA = "..." variables.ViS.iParamNoA = 1 variables.ViS.iParamIdxA = 1 variables.ViS.sSensorNameB = "..." variables.ViS.iSensorNoB = 1 variables.ViS.iSensorIDB = 0 variables.ViS.iSensorIdxB = 1 variables.ViS.iSensorTypeB = 1 variables.ViS.sParamB = "..." variables.ViS.iParamNoB = 1 variables.ViS.iParamIdxB = 1 -- Vorflug Spannungssensor entkoppeln variables.Vor.sSensorName = "..." variables.Vor.iSensorNo = 1 variables.Vor.iSensorID = 0 variables.Vor.iSensorIdx = 1 variables.Vor.iSensorType = 1 variables.Vor.sParam = "..." variables.Vor.iParamNo = 1 variables.Vor.iParamIdx = 1 form.reinit(1) -- Die neu gewählte Sensorwerteliste auch richtig anzeigen --variables.bSpezialSensorenDetach = false --form.setValue(SpezForm, variables.bSpezialSensorenDetach) end end) -- Import *.TXT V7.0.8h addSpacer(318, 10) addRow(2) addLabel({label=trans.SpezialImportTXT, width=200}) index = 1 addSelectbox(filesLoad, index, true, function(value) text = value > 1 and filesLoad[value] or "" local filename = folder..text..extensionFile loadConfig(filename) system.messageBox(trans.Msg_TXTimport..": "..filename, 2) end) -- Alte pSave Variablen löschen local DeleteForm local bDelete = false addRow(2) addLabel({label=trans.DeleteOldVariables, width=275}) DeleteForm = addCheckbox(bDelete, function(value) bDelete = not value form.setValue(DeleteForm, bDelete) if bDelete then print("Löschen") deleteOldVariables() system.messageBox(trans.Msg_VarDelete, 2) end end) end --End option collectgarbage() end local function initForm2() --if (not sorted) then -- sorted = true if (not variables.sorted) then variables.sorted = true tiles = {trans.empty, TelVal.iTVInst1.sTelValName, TelVal.iTVInst2.sTelValName, TelVal.iTVInst3.sTelValName, TelVal.iTVInst4.sTelValName, TelVal.iTVInst5.sTelValName, -- 2 .. 7 TelVal.iTVInst6.sTelValName, TelVal.iTVInst7.sTelValName, TelVal.iTVInst8.sTelValName, TelVal.iTVInst9.sTelValName, TelVal.iTVInst10.sTelValName, -- 8 .. 11 TelVal.iTVInst11.sTelValName, TelVal.iTVInst12.sTelValName, TelVal.iTVInst13.sTelValName, TelVal.iTVInst14.sTelValName, TelVal.iTVInst15.sTelValName, -- 12 .. 16 trans.recminis3, -- 17 -- 33 trans.receivers3, -- 18 -- 34 trans.mtag, -- 19 -- 35 trans.kordinatena, -- 20 -- 36 FlexPics.iFlexPicIdx1.sFlexPicName, FlexPics.iFlexPicIdx2.sFlexPicName, FlexPics.iFlexPicIdx3.sFlexPicName, FlexPics.iFlexPicIdx4.sFlexPicName, FlexPics.iFlexPicIdx5.sFlexPicName, FlexPics.iFlexPicIdx6.sFlexPicName, -- 21 .. 26 trans.drawBarChart, -- 27 trans.receivers1, -- 28 trans.recminis1, -- 29 trans.receivers2, -- 30 trans.recminis2, -- 31 TelVal.iTVInst16.sTelValName, TelVal.iTVInst17.sTelValName, TelVal.iTVInst18.sTelValName, TelVal.iTVInst19.sTelValName, TelVal.iTVInst20.sTelValName, -- 32 .. 36 TelVal.iTVInst21.sTelValName, TelVal.iTVInst22.sTelValName, TelVal.iTVInst23.sTelValName, TelVal.iTVInst24.sTelValName, -- 37 .. 40 trans.menu_Oszi -- 41 } indices = {} for i=1, methodsMax do indices[i] = i if (i > 1) then tiles[i] = string.format("%s (%0d)", tiles[i], heights[i]) end end quicksort(indices, tiles, 2, methodsMax) for i=1, methodsMax do indices[-indices[i]] = i end end local setTitle, addSpacer, addRow = form.setTitle, form.addSpacer, form.addRow local addLabel, addSelectbox, addIntbox = form.addLabel, form.addSelectbox, form.addIntbox local labels = {trans.left, trans.right, trans.middle} setTitle(trans.title2) addRow(2) addLabel({label=trans.telwindows, width=250}) addIntbox(se.telwindows, 1, 3, 1, 0, 1, function(value) se.telwindows = value form.reinit(2) end) for i=1, 3 do local index = se.telwindows * 3 - 3 + i local position = positions[index] local sIndex = string.format("%0d", index) -- local height = heightMax - spacers[-index] local height = heightMax - spacers["-"..sIndex] local used, space for j=1, positionMax do if ( (position[j] > 1) and (heights[position[j]] ~= nil) )then height = height - heights[position[j]] if (heights[position[j]] > 0) then height = height - spacers[sIndex] used = true end end end if (used) then height = height + spacers[sIndex] end local labelSection = string.format("%s (%s %0d)", labels[i], trans.tele, se.telwindows) addSpacer(318, 7) local sheight = string.format("%0d", height) addRow(3) addLabel({label=labelSection.." "..sheight, width=200, font=FONT_BOLD}) addIntbox(spacers["-"..sIndex], 0, 160, 3, 0, 1, function(value) spacers["-"..sIndex] = value form.reinit(formID) end, {width=60}) addIntbox(spacers[sIndex], 0, 160, 1, 0, 1, function(value) spacers[sIndex] = value form.reinit(formID) end, {width=60}) for j=1, positionMax do addRow(2) addLabel({label=trans.pos.." "..(j > positionMax and j - positionMax or j), width=160}) addSelectbox(tiles, indices[-position[j]], true, function(value) local previous = position[j] value = indices[value] counts[previous] = counts[previous] - 1 counts[value] = counts[value] + 1 position[j] = value form.reinit(formID) end) end end collectgarbage() end local function initForm(id) formID = id variables.bCmdSaveSettings = true -- Wenn die normale Anzeige später aufgerufen wird, soll gespeichert werden if (formID == 1) then initForm1() elseif (formID == 2) then initForm2() end form.setButton(1, "1", formID == 1 and HIGHLIGHTED or ENABLED) form.setButton(2, "2", formID == 2 and HIGHLIGHTED or ENABLED) form.setButton(3, "", DISABLED) if (formID == 1) then form.setButton(4, "S", timeVars.B4 and HIGHLIGHTED or metaData.DataStorage.fileForSave:len() > 0 and ENABLED or DISABLED) form.setButton(5, "L", timeVars.B5 and HIGHLIGHTED or metaData.DataStorage.fileForLoad:len() > 0 and ENABLED or DISABLED) else form.setButton(4, "", DISABLED) form.setButton(5, "" , ENABLED) end end local function writeSnapShot() -- Hier werden die aktuellen Werte der TelVals und das Säulendiagramms in eine Snapshot-Textdatei geschrieben local i, text, text2, iPos local dt = system.getDateTime() local sFileName = string.format("SnapShot_%d-%02d-%02d_%d-%02d-%02d", dt.year, dt.mon, dt.day, dt.hour, dt.min, dt.sec) local file = io.open(folder..sFileName..extensionFile, "w+") text = string.format("SnapShot: %d-%02d-%02d, %d:%02d:%02d\n", dt.year, dt.mon, dt.day, dt.hour, dt.min, dt.sec) io.write(file, text) text = string.format(" Model: %s\n", metaData.Model) io.write(file, text) -- GPS Koordinaten schreiben if variables.GPS.iSensorID ~= nil then if variables.GPS.iSensorID > 1 then text = string.format("%s", trans.kordinatena .. ":") io.write(file, text.."\n") local nesw = {"N", "E", "S", "W"} local latDeg = (variables.GPS.Breite >> 16) & 0xFF local latMin = (variables.GPS.Breite & 0xFFFF) * 0.001 text = string.format("%3d\u{B0}%2.3f' %s", latDeg, latMin, nesw[variables.GPS.iLatNachkomma + 1]) io.write(file, text.."\n") local lonDeg = (variables.GPS.Laenge >> 16) & 0xFF local lonMin = (variables.GPS.Laenge & 0xFFFF) * 0.001 text = string.format("%3d\u{B0}%2.3f' %s", lonDeg, lonMin, nesw[variables.GPS.iLonNachkomma + 1]) io.write(file, text.."\n") end end -- Säulendiagramm schreiben if ( (SpecTiles.AkkuTank.iSensorNo1 > 1) or (SpecTiles.AkkuTank.iSensorNo2 > 2) ) then -- Mindestens ein Sensor muß definiert sein text2 = trans.menu_SpKaAkTk iPos= string.find(text2," ",1) text2 = string.sub(text2,1,iPos-1) if(SpecTiles.AkkuTank.iAccOfStorage == 2) then text = string.format("%s 1:", text2) io.write(file, text.."\n") text = string.format(" %s: %s", trans.menu_SpKaAkTkSensorNo, SpecTiles.AkkuTank.sSensorName1) io.write(file, text.."\n") text = string.format(" %s: %s", trans.menu_SpKaAkTkSensorValueNo, SpecTiles.AkkuTank.sSensorValueName1) io.write(file, text.."\n") text = string.format(" %.02f %s", SpecTiles.AkkuTank.fValueAct1, SpecTiles.AkkuTank.sSensorUnit1) io.write(file, text.."\n") text = string.format("%s 2:", text2) io.write(file, text.."\n") text = string.format(" %s: %s", trans.menu_SpKaAkTkSensorNo, SpecTiles.AkkuTank.sSensorName2) io.write(file, text.."\n") text = string.format(" %s: %s", trans.menu_SpKaAkTkSensorValueNo, SpecTiles.AkkuTank.sSensorValueName2) io.write(file, text.."\n") text = string.format(" %.02f %s", SpecTiles.AkkuTank.fValueAct2, SpecTiles.AkkuTank.sSensorUnit2) io.write(file, text.."\n") else text = string.format("%s:", text2) io.write(file, text.."\n") text = string.format(" %s: %s", trans.menu_SpKaAkTkSensorNo, SpecTiles.AkkuTank.sSensorName1) io.write(file, text.."\n") text = string.format(" %s: %s", trans.menu_SpKaAkTkSensorValueNo, SpecTiles.AkkuTank.sSensorValueName1) io.write(file, text.."\n") text = string.format(" %.02f %s", SpecTiles.AkkuTank.fValueAct1, SpecTiles.AkkuTank.sSensorUnit1) io.write(file, text.."\n") end end -- TelVals schreiben for i=1, ACC_OF_TELEVALUES do zeile = string.format("iTVInst%d", i) if (TelVal[zeile].iTelValSensorNo > 1) or (TelVal[zeile].swTelVal ~= nil) then text = string.format("%s: %s [%s]", TelVal[zeile].sTelValName, TelVal[zeile].sTelValHeader, TelVal[zeile].sTelValSensor) io.write(file, text.."\n") if ( TelVal[zeile]["sTelValActText"] == "" ) then text = string.format(" act = %.2f %s", TelVal[zeile].fTelValAct, TelVal[zeile].sTelValEinheit) io.write(file, text.."\n") text = string.format(" min = %.2f %s | max = %.2f %s", TelVal[zeile].fTelValMin, TelVal[zeile].sTelValEinheit, TelVal[zeile].fTelValMax, TelVal[zeile].sTelValEinheit) io.write(file, text.."\n") else text = string.format(" act = %s", TelVal[zeile]["sTelValActText"]) io.write(file, text.."\n") end end end -- MTAG schreiben if variables.MTAG.iSensorID ~= nil then --print(variables.MTAG.iSensorID) if variables.MTAG.iSensorID > 1 then --text = " " io.write(file, text.."\n") text = string.format("%s", trans.menu_MTAGSensorID) io.write(file, text.."\n") text = string.format(" AkkuID: %s", variables.MTAG.iAkkuID) io.write(file, text.."\n") text = string.format(" Cap: %s", variables.MTAG.iCapacity) io.write(file, text.."\n") text = string.format(" Cycles: %s", variables.MTAG.iCycles) io.write(file, text.."\n") text = string.format(" Cells: %s", variables.MTAG.iAccOfCells) io.write(file, text.."\n") text = string.format(" C rate: %s", variables.MTAG.iCrate) io.write(file, text.."\n") text = string.format(" State: %s", variables.MTAG.iState) io.write(file, text.."\n") end end io.close(file) setFiles() -- Liste aktualisieren -- Vorauswahl, die neue SnapShot-Datei einstellen (letzter Eintrag) variables.SnapShot.FileName = variables.SnapShot.Files[variables.SnapShot.FileIndex] variables.SnapShot.FileIndex = #variables.SnapShot.Files end -- ----- FlexPics Default-Werte ----- -- Diese Tabelle enthält die identischen Werte wie in der Initialisierungsschleife. -- Sie wird NIEMALS verändert und dient nur als Vergleichsreferenz. local FlexPicDefaults = { swFlexPic = nil, -- sFlexPicName = dynamisch (wird per Index berechnet, s.u.) sFlexPicHeader = "", sFlexPicFileName1 = "EmptyPic", iFlexPicFileIndex1 = 1, sFlexPicFileName2 = "EmptyPic", iFlexPicFileIndex2 = 1, sFlexPicFileName3 = "EmptyPic", iFlexPicFileIndex3 = 1, iFlexPicHeight = 38, iFlexPicBgColor = 0, iFlexPicAllignmentHorizontal = 2, iFlexPicAllignmentVertikal = 1, fFlexPicLim12 = -49.0, fFlexPicLim23 = 51.0, fFlexPicLim32 = 49.0, fFlexPicLim21 = -51.0 } -- ----- TelVal Default-Werte ----- -- Enthält alle Felder, die per --system.pSave() gespeichert werden, -- mit ihren Initialisierungswerten. local TelValDefaults = { -- sTelValName = dynamisch (wird per Index berechnet, s.u.) sTelValHeader = "", iTelValAllignmentHorizontal = 3, iTelValSize = 2, swTelVal = nil, bSemaPlay = false, -- Initwert Sound nicht wiederholt ausgeben, nur einmal swValPlay = nil, -- Taster/Schalter löst Ansage aus sTelValSensor = "", bCommandPlay = false, -- Kommando zum Einstellen der Sounddatei in die Audioque iLockNewPlay = 0, -- Pause, damit bei Signalschwankungen nicht ständig neue Files in die Audioschlange eingetragen werden. =0 -> freigegeben, >0 -> gesperrt iTelValSensorID = 0, iTelValSensorNo = 1, iTelValSensorIdx = 1, iTelValSensorType = 1, sTelValParam = "", iTelValParamNo = 1, iTelValParamIdx = 1, sTelValEinheit = " ?", sTelValKorrekturfaktor = "1.0", iTelValNachkomma = 1, iTelValHeight = 36, iTelValWidth = 128, iTelValBgColor = 0, -- ACHTUNG: Wird nachträglich individuell überschrieben! fTVTxLim1 = nil, fTVTxLim2 = nil, fTVTxLim3 = nil, fTVTxLim4 = nil, sTVTxText1 = "", sTVTxText2 = "", sTVTxText3 = "", sTVTxText4 = "", iLimBlinkenFreqZael = 6 } -- Individuelle Default-Hintergrundfarben je TelVal-Instanz -- (werden nach der Initialisierungsschleife gesetzt) local TelValBgColorDefaults = { -- [1]=26, [2]=29, ... entspricht TelVal.iTVInst1.iTelValBgColor = 26, etc. [1] = 26, [2] = 29, [3] = 32, [4] = 35, [5] = 4, [6] = 10, [7] = 14, [8] = 6, [9] = 22, [10] = 25, [11] = 28, [12] = 31, [13] = 34, [14] = 37, [15] = 40 } ------------------- -- Save Settings -- ------------------- -- =========================================================================== -- Dieses Skript speichert alle Anwendungseinstellungen in eine JSON-Datei. -- Optimierungen: Reduzierte Code-Duplikation, verbesserte Lesbarkeit, -- generische Hilfsfunktionen für wiederholte Operationen. -- =========================================================================== -- --------------------------------------------------------------------------- -- HILFSFUNKTION: switchToTable -- Wandelt eine Schalter-ID (GeberID) in eine serialisierbare Lua-Tabelle um. -- Gibt nil zurück, wenn kein gültiger Schalter gefunden wurde. -- --------------------------------------------------------------------------- local function switchToTable(switchId) if switchId == nil then return nil end -- Kein Schalter gesetzt local info = system.getSwitchInfo(switchId) -- Systeminformation abfragen if info == nil then return nil end -- Schalter existiert nicht mehr -- Nur die drei für das Speichern relevanten Felder zurückgeben return { label = info.label, mode = info.mode, activeOn = info.activeOn } end -- --------------------------------------------------------------------------- -- HILFSFUNKTION: tableToSwitch -- Wandelt eine gespeicherte Tabelle wieder in eine Schalter-ID (GeberID) um. -- Gibt nil zurück, wenn die Tabelle nil ist. -- --------------------------------------------------------------------------- local function tableToSwitch(t) if t == nil then return nil end -- Nichts zu tun -- system.createSwitch rekonstruiert die GeberID aus label, mode, activeOn return system.createSwitch(t.label, t.mode, t.activeOn) end -- --------------------------------------------------------------------------- -- HILFSFUNKTION: writeLine -- Schreibt eine beliebige Lua-Variable als JSON-Zeile in die Datei. -- --------------------------------------------------------------------------- local function writeLine(file, data) io.write(file, json.encode(data) .. "\n") end -- --------------------------------------------------------------------------- -- HILFSFUNKTION: saveSwitchField -- Sichert ein einzelnes Schalterfeld (switchField) eines Containers (tbl) -- temporär als Tabelle, damit JSON-Serialisierung möglich ist. -- Gibt die Sicherungstabelle zurück (oder nil). -- Das Original-Feld im Container wird dabei ÜBERSCHRIEBEN. -- Nach dem Schreiben muss restoreSwitchField() aufgerufen werden. -- --------------------------------------------------------------------------- local function saveSwitchField(tbl, fieldName) local backup = switchToTable(tbl[fieldName]) -- GeberID → Tabelle tbl[fieldName] = backup -- Feld im Container ersetzen return backup -- Backup für spätere Wiederherstellung end -- --------------------------------------------------------------------------- -- HILFSFUNKTION: restoreSwitchField -- Stellt ein Schalterfeld im Container aus dem Backup wieder her. -- --------------------------------------------------------------------------- local function restoreSwitchField(tbl, fieldName, backup) if backup ~= nil then -- Tabelle → GeberID zurückwandeln tbl[fieldName] = tableToSwitch(backup) else tbl[fieldName] = nil -- Schalter war nicht gesetzt end end -- --------------------------------------------------------------------------- -- NEUE HILFSFUNKTION: backupImageFields -- Sichert mehrere Bildfelder eines Objekts und setzt sie temporär auf nil. -- Gibt eine Backup-Tabelle zurück. -- --------------------------------------------------------------------------- local function backupImageFields(obj, fieldNames) local backup = {} for _, fieldName in ipairs(fieldNames) do if obj[fieldName] ~= nil then backup[fieldName] = obj[fieldName] obj[fieldName] = nil end end return backup end -- --------------------------------------------------------------------------- -- NEUE HILFSFUNKTION: restoreImageFields -- Stellt mehrere Bildfelder aus einem Backup wieder her. -- --------------------------------------------------------------------------- local function restoreImageFields(obj, backup) for fieldName, value in pairs(backup) do obj[fieldName] = value end end -- --------------------------------------------------------------------------- -- NEUE HILFSFUNKTION: convertSensorIDsToString -- Wandelt mehrere Sensor-IDs in Strings um (verhindert Float-Konvertierung). -- Gibt eine Backup-Tabelle mit den Original-Feldnamen zurück. -- --------------------------------------------------------------------------- local function convertSensorIDsToString(obj, fieldNames) local backup = {} for _, fieldName in ipairs(fieldNames) do if obj[fieldName] ~= nil then backup[fieldName] = obj[fieldName] obj[fieldName] = string.format("%d", obj[fieldName]) end end return backup end -- --------------------------------------------------------------------------- -- NEUE HILFSFUNKTION: restoreSensorIDs -- Wandelt String-Sensor-IDs zurück in Zahlen. -- --------------------------------------------------------------------------- local function restoreSensorIDs(obj, backup) for fieldName, _ in pairs(backup) do obj[fieldName] = tonumber(obj[fieldName]) end end -- --------------------------------------------------------------------------- -- NEUE HILFSFUNKTION: convertTimeVarsToString -- Wandelt alle Zeit-Variablen in Strings um (verhindert Float-Konvertierung). -- Gibt eine neue Tabelle mit String-Werten zurück. -- --------------------------------------------------------------------------- local function convertTimeVarsToString(timeVars) local sText = {} local timeFields = { "eTime", "fTime", "cTime", "bTime", "qTime1", "a1Time1", "a2Time1", "qTime2", "a1Time2", "a2Time2", "qTimeB", "a1TimeB", "a2TimeB", "eLastTime", "fLastTime", "cLastTime", "timeModel" } for _, fieldName in ipairs(timeFields) do if timeVars[fieldName] ~= nil then sText[fieldName] = string.format("%d", timeVars[fieldName]) end end return sText end -- =========================================================================== -- HAUPTFUNKTION: saveSettings -- Speichert alle Einstellungen der Anwendung in eine JSON-Datei. -- Dateiname: "DApp_" -- =========================================================================== local function saveSettings(fileToSave) --print(string.format("saveSettings: übergebener Dateiname: %s", fileToSave)) local filePath if (fileToSave == nil) or (type(fileToSave) ~= "string") then -- Kein Dateiname übergeben --> Standarddateiname prüfen -- Frühzeitiger Abbruch wenn kein Modell-Dateiname vorhanden ist if jsnModelFile:len() == 0 then return end filePath = jsnModelFile else -- Mit dem übergebenen Dateinamen speichern -- Frühzeitiger Abbruch wenn kein Modell-Dateiname vorhanden ist if type(fileToSave) == "string" then if fileToSave:len() == 0 then return end filePath = folder .. fileToSave else -- Es ist eine Zahl vorhanden return end end --print("saveSettings: "..filePath) -- Datei öffnen (w+ = Schreiben, neu anlegen / überschreiben) local file = io.open(filePath, "w+") if not file then return false end -- Datei konnte nicht geöffnet werden -- Aktuelles Datum speichern local dt = system.getDateTime() metaData.SaveDate = string.format("%02d.%02d.%d %02d:%02d:%02d", dt.day, dt.mon, dt.year, dt.hour, dt.min, dt.sec) -- Variable löschen, da sie immer bei Notwendigkeit neu geladen werden müssen (Bilder) if se.warning ~= nil then se.warning = nil end if se.warning1 ~= nil then se.warning1 = nil end if se.warning2 ~= nil then se.warning2 = nil end if se.akkuAlert ~= nil then se.akkuAlert = nil end -- ----------------------------------------------------------------------- -- 1) Metadaten und globale Konfigurationen schreiben -- Reihenfolge entspricht dem originalen Format – NICHT ändern! -- ----------------------------------------------------------------------- writeLine(file, metaData) -- Modell-Metadaten --print("metaData") writeLine(file, positions) -- Positionen der Tiles --print("positions") writeLine(file, params) -- Allgemeine Parameter --print("params") writeLine(file, spacers) -- Spacer-Konfiguration --print("spacers") writeLine(file, se) -- Sound-Events --print("se") -- ----------------------------------------------------------------------- -- 2) Globale Schalter (sw-Tabelle) speichern -- Schalter-IDs (GeberIDs) können nicht direkt als JSON gespeichert werden. -- Sie werden daher vorher in Tabellen umgewandelt und danach wiederhergestellt. -- ----------------------------------------------------------------------- -- Liste aller Schalterfelder in der sw-Tabelle -- Neue Schalter hier einfach ergänzen – kein weiterer Code nötig! local swFields = { "beepSw", "beepPauseSw", "an3Sw", "an4Sw", "capaSw", "speedSw", "engineSw", "assSw", "flightSw", "timerSw", "flightsSw", "varihoheSw", "maxSw", "minSw", "statsTimeSw", "statsFlightSw", "resetTimeSw", "resetRxSw", "resetTeleSw", "resetStatsSw", "resetmimaSw", "SnapShotSw", "startBeepTimerSw","pauseBeepTimerSw","resetBeepTimerSw", "startFlightTimerSw","pauseFlightTimerSw","resetFlightTimerSw", "startCountdownTimerSw","pauseCountdownTimerSw","resetCountdownTimerSw","resetMotorTimerSw", "switchTilesSw","OsziStartSw","OsziStoppSw","OsziResetSw","OsziSaveSw","OsziLoadSw","OsziOneShotSw" } -- Schritt 1: Alle GeberIDs → Tabellen umwandeln, Backups merken local swBackups = {} for _, fieldName in ipairs(swFields) do swBackups[fieldName] = saveSwitchField(sw, fieldName) end -- Schritt 2: sw-Tabelle (jetzt nur noch einfache Werte) als JSON schreiben writeLine(file, sw) --print("sw") -- Schritt 3: Alle Schalterfelder aus den Backups wiederherstellen for _, fieldName in ipairs(swFields) do restoreSwitchField(sw, fieldName, swBackups[fieldName]) end -- ----------------------------------------------------------------------- -- 3) FlexPics speichern (6 Einträge) -- Jedes FlexPic enthält einen Schalter (swFlexPic) und Bildfelder. -- ----------------------------------------------------------------------- local imageFields = {"imgFlexPic1", "imgFlexPic2", "imgFlexPic3"} for i = 1, 6 do local key = string.format("iFlexPicIdx%d", i) local fp = FlexPics[key] -- Schalter temporär als Tabelle speichern local switchBackup = saveSwitchField(fp, "swFlexPic") -- Bildfelder temporär sichern und auf nil setzen local imageBackup = backupImageFields(fp, imageFields) -- FlexPic-Eintrag als JSON schreiben writeLine(file, fp) -- Bildfelder wiederherstellen restoreImageFields(fp, imageBackup) -- Schalter wiederherstellen restoreSwitchField(fp, "swFlexPic", switchBackup) end --print("FlexPics") -- ----------------------------------------------------------------------- -- 4) TeleValues speichern (ACC_OF_TELEVALUES Einträge) -- Jeder TeleValue enthält einen optionalen Schalter (swTelVal). -- ----------------------------------------------------------------------- for i = 1, ACC_OF_TELEVALUES do local key = string.format("iTVInst%d", i) local tv = TelVal[key] -- Schalter temporär als Tabelle speichern local switchBackup = saveSwitchField(tv, "swTelVal") local switchSoundBackup = saveSwitchField(tv, "swValPlay") -- Sensor-ID in String umwandeln local sensorBackup = convertSensorIDsToString(tv, {"iTelValSensorID"}) -- TeleValue-Eintrag als JSON schreiben writeLine(file, tv) -- Sensor-ID zurückwandeln restoreSensorIDs(tv, sensorBackup) -- Schalter wiederherstellen restoreSwitchField(tv, "swValPlay", switchSoundBackup) restoreSwitchField(tv, "swTelVal", switchBackup) end --print("TeleValues") -- ----------------------------------------------------------------------- -- 5) Spezial-Tiles, Steuerungsvariablen und Sensordaten schreiben -- ----------------------------------------------------------------------- -- AkkuTank-Tile verarbeiten local imgBackup = nil if SpecTiles.AkkuTank.imgPicFile ~= nil then imgBackup = SpecTiles.AkkuTank.imgPicFile SpecTiles.AkkuTank.imgPicFile = nil end -- Schalter temporär als Tabelle speichern local backup1 = saveSwitchField(SpecTiles.AkkuTank, "swValPlay1") local backup2 = saveSwitchField(SpecTiles.AkkuTank, "swValPlay2") -- Sensor-IDs in Strings umwandeln local akkuSensorBackup = convertSensorIDsToString(SpecTiles.AkkuTank, {"iSensorId1", "iSensorId2"}) writeLine(file, SpecTiles.AkkuTank) -- Säulendiagramm (AkkuTank-Tile) --print("BarChart") -- Sensor-IDs zurückwandeln restoreSensorIDs(SpecTiles.AkkuTank, akkuSensorBackup) -- Schalter wiederherstellen restoreSwitchField(SpecTiles.AkkuTank, "swValPlay1", backup1) restoreSwitchField(SpecTiles.AkkuTank, "swValPlay2", backup2) -- Bilddatei wiederherstellen if imgBackup ~= nil then SpecTiles.AkkuTank.imgPicFile = imgBackup end -- Weitere Variablen schreiben writeLine(file, variables.column) -- Spaltensteuerung writeLine(file, variables.SnapShot) -- Snapshot-Daten writeLine(file, variables.Ans) -- Ansage-Daten -- MTAG-Daten local mtagBackup = convertSensorIDsToString(variables.MTAG, {"iSensorID"}) writeLine(file, variables.MTAG) restoreSensorIDs(variables.MTAG, mtagBackup) -- GPS-Daten local gpsBackup = convertSensorIDsToString(variables.GPS, {"iSensorID"}) writeLine(file, variables.GPS) restoreSensorIDs(variables.GPS, gpsBackup) -- Virtueller Sensor local visBackup = convertSensorIDsToString(variables.ViS, {"iSensorIDA", "iSensorIDB"}) writeLine(file, variables.ViS) restoreSensorIDs(variables.ViS, visBackup) -- Vorflug-Sensor local vorBackup = convertSensorIDsToString(variables.Vor, {"iSensorID"}) writeLine(file, variables.Vor) --print("Vorflug-Sensor") restoreSensorIDs(variables.Vor, vorBackup) -- Zeiten in Text wandeln, damit Integer nicht in Float-Werte gewandelt werden local sText = convertTimeVarsToString(timeVars) writeLine(file, sText) -- Zeiten --print("Zeiten") writeLine(file, timeHMS) -- Zerlegte Zeiten --print("Zerlegte Zeiten") writeLine(file, variables.Collect) -- Gesammelte Einzelvariablen --print("Lumpensammler") writeLine(file, variables.BeepCmd) -- Timer Beep Kontrollen --print("TimerBeep Kontrollen") -- Oszilloskop -- speichern Oszi.TVlist = nil -- Dieses Feld soll immer wieder neu angelegt werden, nicht abspeichern. -- Datenfelder nicht abspeichern Oszi.Data.Values.Ch1.Point = nil Oszi.Data.Values.Ch1.Time = nil Oszi.Data.Values.Ch2.Point = nil Oszi.Data.Values.Ch2.Time = nil Oszi.Data.Values.Ch3.Point = nil Oszi.Data.Values.Ch3.Time = nil Oszi.Data.Values.Ch4.Point = nil Oszi.Data.Values.Ch4.Time = nil writeLine(file, Oszi) -- Oszilloskop --print("Oszilloskop") ResetOsziData() -- Alle Felder richtig initialisieren writeLine(file, variables.Rex.Selected) -- Farben für die Empfängerkacheln --print("Farben für Empfängerkacheln") -- ----------------------------------------------------------------------- -- 6) Datei schließen -- ----------------------------------------------------------------------- io.close(file) system.messageBox(trans.Msg_JSNsave, 1) return true -- erfolgreich end -- saveSettings -- =========================================================================== -- OPTIMIERTE VERSION: loadSettings.lua -- =========================================================================== -- Dieses Skript lädt alle Anwendungseinstellungen aus einer JSON-Datei. -- Gegenstück zu saveSettings.lua - verwendet die gleichen Optimierungsprinzipien. -- =========================================================================== -- --------------------------------------------------------------------------- -- HILFSFUNKTION: switchToTable -- Wandelt eine Schalter-ID (GeberID) in eine serialisierbare Lua-Tabelle um. -- Gibt nil zurück, wenn kein gültiger Schalter gefunden wurde. -- --------------------------------------------------------------------------- local function switchToTable(switchId) if switchId == nil then return nil end -- Kein Schalter gesetzt local info = system.getSwitchInfo(switchId) -- Systeminformation abfragen if info == nil then return nil end -- Schalter existiert nicht mehr -- Nur die drei für das Speichern relevanten Felder zurückgeben return { label = info.label, mode = info.mode, activeOn = info.activeOn } end -- --------------------------------------------------------------------------- -- HILFSFUNKTION: tableToSwitch -- Wandelt eine gespeicherte Tabelle wieder in eine Schalter-ID (GeberID) um. -- Gibt nil zurück, wenn die Tabelle nil ist. -- --------------------------------------------------------------------------- local function tableToSwitch(t) if t == nil then return nil end -- Nichts zu tun -- system.createSwitch rekonstruiert die GeberID aus label, mode, activeOn return system.createSwitch(t.label, t.mode, t.activeOn) end -- --------------------------------------------------------------------------- -- HILFSFUNKTION: readLine -- Liest eine Zeile aus der Datei und dekodiert sie als JSON. -- Gibt die dekodierte Lua-Tabelle zurück. -- --------------------------------------------------------------------------- local function readLine(file) local line = io.readline(file) if line == nil or line == "" then return nil end return json.decode(line) end -- --------------------------------------------------------------------------- -- NEUE HILFSFUNKTION: restoreSwitchFields -- Wandelt mehrere Schalterfelder von Tabellen zurück in GeberIDs. -- Arbeitet direkt auf dem Zielobjekt. -- --------------------------------------------------------------------------- local function restoreSwitchFields(obj, fieldNames) for _, fieldName in ipairs(fieldNames) do if obj[fieldName] ~= nil then obj[fieldName] = tableToSwitch(obj[fieldName]) end end end -- --------------------------------------------------------------------------- -- NEUE HILFSFUNKTION: convertSensorIDsToNumber -- Wandelt mehrere Sensor-IDs von Strings zurück in Zahlen. -- Arbeitet direkt auf dem Zielobjekt. -- --------------------------------------------------------------------------- local function convertSensorIDsToNumber(obj, fieldNames) for _, fieldName in ipairs(fieldNames) do if obj[fieldName] ~= nil then obj[fieldName] = tonumber(obj[fieldName]) end end end -- --------------------------------------------------------------------------- -- NEUE HILFSFUNKTION: convertTimeVarsToNumber -- Wandelt alle Zeit-Variablen von Strings zurück in Zahlen. -- Gibt die konvertierte Tabelle zurück. -- --------------------------------------------------------------------------- local function convertTimeVarsToNumber(sText) local timeVars = {} local timeFields = { "eTime", "fTime", "cTime", "bTime", "qTime1", "a1Time1", "a2Time1", "qTime2", "a1Time2", "a2Time2", "qTimeB", "a1TimeB", "a2TimeB", "eLastTime", "fLastTime", "cLastTime", "timeModel" } for _, fieldName in ipairs(timeFields) do if sText[fieldName] ~= nil then timeVars[fieldName] = tonumber(sText[fieldName]) end end return timeVars end -- =========================================================================== -- HAUPTFUNKTION: loadSettings -- Lädt alle Einstellungen der Anwendung aus einer JSON-Datei. -- Dateiname: "<folder>DApp_<metaData.ModelFileName>" -- =========================================================================== local function loadSettings(fileToLoad) local filePath if fileToLoad == nil then -- Kein Dateiname übergeben -->; Standarddateiname prüfen -- Frühzeitiger Abbruch wenn kein Modell-Dateiname vorhanden ist if jsnModelFile:len() == 0 then return false end filePath = jsnModelFile else -- Mit dem übergebenen Dateinamen laden -- Frühzeitiger Abbruch wenn kein Modell-Dateiname vorhanden ist if fileToLoad:len() == 0 then return false end filePath = folder .. fileToLoad end --print("loadSettings: "..filePath) -- Datei öffnen (r = Lesen) local file = io.open(filePath, "r") if not file then -- print("Datei "..filePath.. " konnte nicht geöffnet werden!") return false end -- ----------------------------------------------------------------------- -- 1) Metadaten und globale Konfigurationen lesen -- Reihenfolge entspricht dem Speicherformat – NICHT ändern! -- ----------------------------------------------------------------------- metaData = readLine(file) -- Modell-Metadaten if metaData == nil then io.close(file) print("Fehler: Ungültiges Dateiformat!") return false end positions = readLine(file) -- Positionen der Tiles params = readLine(file) -- Allgemeine Parameter spacers = readLine(file) -- Spacer-Konfiguration se = readLine(file) -- Sound-Events --print("se geladen") -- ----------------------------------------------------------------------- -- 2) Globale Schalter (sw-Tabelle) laden -- Schalter wurden als Tabellen gespeichert und müssen zurückgewandelt werden. -- ----------------------------------------------------------------------- -- Liste aller Schalterfelder in der sw-Tabelle -- Muss identisch mit saveSettings sein! local swFields = { "beepSw", "beepPauseSw", "an3Sw", "an4Sw", "capaSw", "speedSw", "engineSw", "assSw", "flightSw", "timerSw", "flightsSw", "varihoheSw", "maxSw", "minSw", "statsTimeSw", "statsFlightSw", "resetTimeSw", "resetRxSw", "resetTeleSw", "resetStatsSw", "resetmimaSw", "SnapShotSw", "startBeepTimerSw","pauseBeepTimerSw","resetBeepTimerSw", "startFlightTimerSw","pauseFlightTimerSw","resetFlightTimerSw", "startCountdownTimerSw","pauseCountdownTimerSw","resetCountdownTimerSw","resetMotorTimerSw", "switchTilesSw","OsziStartSw","OsziStoppSw","OsziResetSw","OsziSaveSw","OsziLoadSw","OsziOneShotSw" } -- sw-Tabelle aus Datei lesen sw = readLine(file) -- Alle Schalterfelder von Tabellen zurück in GeberIDs wandeln restoreSwitchFields(sw, swFields) -- ----------------------------------------------------------------------- -- 3) FlexPics laden (6 Einträge) -- Jedes FlexPic enthält einen Schalter (swFlexPic). -- ----------------------------------------------------------------------- for i = 1, 6 do local key = string.format("iFlexPicIdx%d", i) FlexPics[key] = readLine(file) -- Schalter von Tabelle zurück in GeberID wandeln restoreSwitchFields(FlexPics[key], {"swFlexPic"}) end -- ----------------------------------------------------------------------- -- 4) TeleValues laden (ACC_OF_TELEVALUES Einträge) -- Jeder TeleValue enthält einen optionalen Schalter (swTelVal). -- ----------------------------------------------------------------------- -- Zum Laden der alten 7.0.1 Dateien, müssen nur 15 Televalues geladen werden local iAcc = ACC_OF_TELEVALUES if metaData.Version == "7.1.0" then iAcc = 15 -- Alte Anzahl der TeleValues end for i = 1, iAcc do local key = string.format("iTVInst%d", i) TelVal[key] = readLine(file) -- Sensor-ID von String zurück in Zahl wandeln convertSensorIDsToNumber(TelVal[key], {"iTelValSensorID"}) -- Schalter von Tabelle zurück in GeberID wandeln restoreSwitchFields(TelVal[key], {"swTelVal"}) restoreSwitchFields(TelVal[key], {"swValPlay"}) end -- ----------------------------------------------------------------------- -- 5) Spezial-Tiles, Steuerungsvariablen und Sensordaten laden -- ----------------------------------------------------------------------- -- AkkuTank-Tile laden SpecTiles.AkkuTank = readLine(file) -- Sensor-IDs von Strings zurück in Zahlen wandeln convertSensorIDsToNumber(SpecTiles.AkkuTank, {"iSensorId1", "iSensorId2"}) -- Schalter von Tabellen zurück in GeberIDs wandeln restoreSwitchFields(SpecTiles.AkkuTank, {"swValPlay1", "swValPlay2"}) -- Weitere Variablen laden variables.column = readLine(file) -- Spaltensteuerung variables.SnapShot = readLine(file) -- Snapshot-Daten variables.Ans = readLine(file) -- Ansage-Daten -- MTAG-Daten laden variables.MTAG = readLine(file) convertSensorIDsToNumber(variables.MTAG, {"iSensorID"}) -- GPS-Daten laden variables.GPS = readLine(file) convertSensorIDsToNumber(variables.GPS, {"iSensorID"}) -- Virtueller Sensor laden variables.ViS = readLine(file) convertSensorIDsToNumber(variables.ViS, {"iSensorIDA", "iSensorIDB"}) -- Vorflug-Sensor laden variables.Vor = readLine(file) --print("Vorflug-Sensor geladen") convertSensorIDsToNumber(variables.Vor, {"iSensorID"}) -- Zeiten laden und von Strings zurück in Zahlen wandeln local sText = readLine(file) if sText ~= nil then -- Zeit-Variablen in timeVars-Tabelle konvertieren for fieldName, value in pairs(convertTimeVarsToNumber(sText)) do timeVars[fieldName] = value end end --print("Zeiten geladen") timeHMS = readLine(file) -- Zerlegte Zeiten --print("Zerlegte Zeiten geladen") variables.Collect = readLine(file) -- Gesammelte Einzelvariablen --print("Lumpensammler geladen") variables.BeepCmd = readLine(file) -- Timer Beep Kontrollen --print("TimerBeep Kontrollen geladen") local temp = {} -- Temporäre Variable, falls noch kein Oszilloskop gespeichert wurde temp = readLine(file) -- Oszilloskop if temp ~= nil then Oszi = temp end --print("Oszilloskop geladen") variables.Rex.Selected = readLine(file) -- Farben für die Empfängerkacheln --print("Farben für Empfängerkacheln geladen") -- ----------------------------------------------------------------------- -- 6) Datei schließen -- ----------------------------------------------------------------------- io.close(file) system.messageBox(trans.Msg_JSNload, 1) -- ----------------------------------------------------------------------- -- Variablen in Ausgangszustand setzen, unabhängig vom geladenen Wert -- ----------------------------------------------------------------------- UpdateHeights() variables.Sensors[variables.CountdownTimeIdx].valSec = timeHMS.cSec variables.Sensors[variables.CountdownTimeIdx].valMin = timeHMS.cMin variables.Sensors[variables.FightsIdx].valTotal = variables.Collect.flightsTotal variables.Sensors[variables.FightsIdx].valToday = variables.Collect.flightsToday variables.Sensors[variables.TimerBeepIdx].valSec = timeHMS.bSec variables.Sensors[variables.TimerBeepIdx].valMin = timeHMS.bMin variables.BeepCmd.iState = -1 -- Command Datei laden if variables.BeepCmd.File ~= nil then if (variables.BeepCmd.File ~= "...") and (variables.BeepCmd.File:len() ~= 0) then local file = io.readall(folder..variables.BeepCmd.File..extensionJsonFile) variables.Sensors[variables.TimerBeepIdx].TimerBeepCmd = json.decode(file) end end -- Timer Beep zurücksetzen (Ausgangszustand) bTimerBeepRuns = false variables.BeepCmd.iState = -1 timeVars.bTime = nil timeHMS.bMin = se.beepMin timeHMS.bSec = se.beepSec variables.Sensors[variables.TimerBeepIdx].valSec = timeHMS.bSec variables.Sensors[variables.TimerBeepIdx].valMin = timeHMS.bMin variables.Sensors[variables.TimerBeepIdx].valTxColor = nil variables.Sensors[variables.TimerBeepIdx].valBgColor = nil variables.Sensors[variables.TimerBeepIdx].valSign = false -- Timer Countdown zurücksetzen timeVars.cTime = nil timeVars.cLastTime = system.getTimeCounter() timeVars.cTime = 60*se.countdownMin + se.countdownSec timeHMS.cMin = se.countdownMin timeHMS.cSec = se.countdownSec variables.Sensors[variables.CountdownTimeIdx].valSec = timeHMS.cSec variables.Sensors[variables.CountdownTimeIdx].valMin = timeHMS.cMin --print(string.format("timeVars.fTime=%s se.TimerZeitSpeichern=%s", timeVars.fTime, se.TimerZeitSpeichern)) if not se.TimerZeitSpeichern then -- Timer Motorzeit zurücksetzen timeVars.eTime = nil timeHMS.eMin, timeHMS.eSec = 0, 0 timeVars.eLastTime = 0 variables.Sensors[variables.MotorTimeIdx].valSec = timeHMS.eSec variables.Sensors[variables.MotorTimeIdx].valMin = timeHMS.eMin -- Timer Flugzeit zurücksetzen timeVars.fTime = nil timeHMS.fHrs, timeHMS.fMin, timeHMS.fSec = 0, 0, 0 timeVars.fLastTime = 0 variables.Sensors[variables.FlightTimeIdx].valSec = timeHMS.fSec variables.Sensors[variables.FlightTimeIdx].valMin = timeHMS.fMin variables.Sensors[variables.FlightTimeIdx].valHour = timeHMS.fHrs else local timeMil = system.getTimeCounter() -- Systemzeit im ms einlesen -- geladene Motorzeit an die Variablen weiterleiten if timeVars.eTime then -- print(string.format("eLastTime=%s eTime=%s timeHMS.eMin=%s timeHMS.eSec=%s", eLastTime, eTime, timeHMS.eMin, timeHMS.eSec)) timeHMS.eMin = math.floor(timeVars.eTime/60) % 60 timeHMS.eSec = timeVars.eTime % 60 variables.Sensors[variables.MotorTimeIdx].valSec = timeHMS.eSec variables.Sensors[variables.MotorTimeIdx].valMin = timeHMS.eMin end -- geladene Flugzeit an die Variablen weiterleiten if timeVars.fTime then timeHMS.fHrs = math.floor(timeVars.fTime/3600) timeHMS.fMin = math.floor(timeVars.fTime/60) % 60 timeHMS.fSec = timeVars.fTime % 60 variables.Sensors[variables.FlightTimeIdx].valSec = timeHMS.fSec variables.Sensors[variables.FlightTimeIdx].valMin = timeHMS.fMin variables.Sensors[variables.FlightTimeIdx].valHour = timeHMS.fHrs end end -- Wichtig, nach einem App-Absturz gehen die Modellspezifischen Daten verloren. system.pSave("showPilotName", se.nickname and 1 or 0) se.option = 1 se.telwindows = 1 se.datens = 1 metaData.DataStorage.fileForLoad = "" -- Variablen löschen, da sie immer bei Notwendigkeit neu geladen werden müssen (Bilder) if se.warning ~= nil then se.warning = nil end if se.warning1 ~= nil then se.warning1 = nil end if se.warning2 ~= nil then se.warning2 = nil end if se.akkuAlert ~= nil then se.akkuAlert = nil end if variables.Collect.flightsTotal == nil then variables.Collect.flightsTotal = 0 end if variables.Collect.flightsToday == nil then variables.Collect.flightsToday = 0 end --------------------------------- -- Empfängerüberwachung -- REX -- --------------------------------- -- Alle Zeitstufen in den Startzustand timeVars.qTime1 = 0 timeVars.a1Time1 = 0 timeVars.a2Time1 = 0 timeVars.qTime2 = 0 timeVars.a1Time2 = 0 timeVars.a2Time2 = 0 timeVars.qTimeB = 0 timeVars.a1TimeB = 0 timeVars.a2TimeB = 0 -- Überwachung und Farben für die Empfängerkacheln if variables.Rex.Selected == nil then -- Noch nicht gespeichert -> Standardeinstellung variables.Rex.Selected = {} variables.Rex.Selected.Index = 1 -- Default variables.Rex.Selected.sTyp = trans.menu_Rex_ModTyp1 -- Beschriftung variables.Rex.Selected.Qlimit = 80 -- Grenzwert in % variables.Rex.Selected.Qtime = 3000 -- Verzögerungszeit in ms variables.Rex.Selected.A1limit = 7 -- Wert 0 - 9 variables.Rex.Selected.A1time = 5000 -- Verzögerungszeit in ms variables.Rex.Selected.A2limit = 7 -- Wert 0 - 9 variables.Rex.Selected.A2time = 5000 -- Verzögerungszeit in ms variables.Rex.Selected.SoundQ = "" variables.Rex.Selected.SoundA1 = "" variables.Rex.Selected.SoundA2 = "" variables.Rex.Selected.SoundA1A2 = "" -- Wenn dieser Sound definiert ist, müssen zum Abspielen beide Antennen schlecht sein -- Farben für die Empfängerkacheln variables.Rex.Selected.txColorON = 43 -- Schwarz variables.Rex.Selected.txColorOFF = 44 -- Weiß variables.Rex.Selected.bgColorON = 29 -- Grün variables.Rex.Selected.bgColorOFF = 23 -- Rot variables.Rex.Selected.txColorONerror = 35 -- Blau variables.Rex.Selected.txColorOFFerror = 34 -- Hell Blau elseif variables.Rex.Selected.Qlimit == nil then variables.Rex.Selected.Index = 1 -- Default variables.Rex.Selected.sTyp = trans.menu_Rex_ModTyp1 -- Beschriftung variables.Rex.Selected.Qlimit = 80 -- Grenzwert in % variables.Rex.Selected.Qtime = 3000 -- Verzögerungszeit in ms variables.Rex.Selected.A1limit = 7 -- Wert 0 - 9 variables.Rex.Selected.A1time = 5000 -- Verzögerungszeit in ms variables.Rex.Selected.A2limit = 7 -- Wert 0 - 9 variables.Rex.Selected.A2time = 5000 -- Verzögerungszeit in ms variables.Rex.Selected.SoundQ = "" variables.Rex.Selected.SoundA1 = "" variables.Rex.Selected.SoundA2 = "" variables.Rex.Selected.SoundA1A2 = "" -- Wenn dieser Sound definiert ist, müssen zum Abspielen beide Antennen schlecht sein -- Farben für die Empfängerkacheln variables.Rex.Selected.txColorON = 43 -- Schwarz variables.Rex.Selected.txColorOFF = 44 -- Weiß variables.Rex.Selected.bgColorON = 29 -- Grün variables.Rex.Selected.bgColorOFF = 23 -- Rot variables.Rex.Selected.txColorONerror = 35 -- Blau variables.Rex.Selected.txColorOFFerror = 34 -- Hell Blau end -- Absicherung local idx for idx=1, ACC_OF_TELEVALUES do local Idx = string.format("iTVInst%d", idx) local tv = TelVal[Idx] if tv.bSemaPlay == nil then -- Werte in den Ausgangszustand tv.bSemaPlay = false -- Initwert Sound nicht wierholt ausgeben, nur einmal tv.swValPlay = nil -- Taster/Schalter löst Ansage aus tv.bCommandPlay = false -- Kommando zum Einstellen der Sounddatei in die Audioque tv.iLockNewPlay = 0 -- Pause, damit bei Signalschwankungen nicht ständig neue Files in die Audioschlange eingetragen werden. =0 -> freigegeben, >0 -> gesperrt end end -- Daten für das Oszilloskop anlegen und initialisieren ------------------------------------------------------- Oszi.Data.oTime = nil ResetOsziData() -- Alle Felder richtig initialisieren return true -- erfolgreich end -- loadSettings -- Telemetriefenster 1 function ka.drawPage1(width, height) -- Automatisches Speichern nach Projektierung if variables.bCmdSaveSettings then variables.bCmdSaveSettings = false saveSettings() UpdateHeights() end if variables.bCmdLoadSettings then variables.bCmdLoadSettings = false loadSettings(nil) end setTextColorDependBG(43, 255, 0) drawBackground() if (switchTiles == 1) then ka.drawTiles(1, variables.column.Left ) -- left ka.drawTiles(2, variables.column.Right ) -- right ka.drawTiles(3, variables.column.Middle) -- middle elseif (switchTiles == -1) then ka.drawTiles(7, variables.column.Left ) -- left ka.drawTiles(8, variables.column.Right ) -- right ka.drawTiles(9, variables.column.Middle) -- middle elseif (switchTiles == 0) then ka.drawTiles(4, variables.column.Left ) -- left ka.drawTiles(5, variables.column.Right ) -- right ka.drawTiles(6, variables.column.Middle) -- middle else ka.drawTiles(1, variables.column.Left ) -- left ka.drawTiles(2, variables.column.Right ) -- right ka.drawTiles(3, variables.column.Middle) -- middle end end -- Telemetriefenster 2 function ka.drawPage2(width, height) -- Automatisches Speichern nach Projektierung if variables.bCmdSaveSettings then variables.bCmdSaveSettings = false saveSettings() UpdateHeights() end if variables.bCmdLoadSettings then variables.bCmdLoadSettings = false loadSettings(nil) end setTextColorDependBG(43, 255, 0) drawBackground() ka.drawTiles(4, variables.column.Left ) -- left ka.drawTiles(5, variables.column.Right ) -- right ka.drawTiles(6, variables.column.Middle) -- middle end --------------------------------------------------------------------------------- local function keyForm(key) if (key == KEY_1) then if (formID ~= 1) then form.reinit(1) end elseif (key == KEY_2) then if (formID ~= 2) then form.reinit(2) end -- elseif (key == KEY_3) then -- if (formID ~= 3) then -- form.reinit(3) -- end elseif (key == KEY_4) then if (formID == 1) then saveSettings(metaData.DataStorage.fileForSave) form.reinit(1) elseif (formID ~= 4) then --form.reinit(4) end elseif (key == KEY_5) then form.preventDefault() if (formID == 1) then loadSettings(metaData.DataStorage.fileForLoad) --form.reinit(1) end end end local function setButtons() if (timeVars.B4 or timeVars.B5) then local time = system.getTimeCounter() local limit = 1000 if (timeVars.B4 and time - timeVars.B4 > limit) then timeVars.B4 = nil if (formID == 1) then form.setButton(4, "S", metaData.DataStorage.fileForSave:len() > 0 and ENABLED or DISABLED) end end if (timeVars.B5 and time - timeVars.B5 > limit) then timeVars.B5 = nil if (formID == 1) then form.setButton(5, "L", metaData.DataStorage.fileForLoad:len() > 0 and ENABLED or DISABLED) end end end end local function setTimers() local startFlightTimer = system.getInputsVal(sw.startFlightTimerSw) -- Der Startgeber kann auch ein Taster sein. Der Start wird gemerkt. local pauseFlightTimer = system.getInputsVal(sw.pauseFlightTimerSw) local resetFlightTimer = system.getInputsVal(sw.resetFlightTimerSw) local resetMotorTimer = system.getInputsVal(sw.resetMotorTimerSw) local startTimerBeep = system.getInputsVal(sw.startBeepTimerSw) local pauseTimerBeep = system.getInputsVal(sw.pauseBeepTimerSw) local resetTimerBeep = system.getInputsVal(sw.resetBeepTimerSw) local startTimerCountdown = system.getInputsVal(sw.startCountdownTimerSw) local pauseTimerCountdown = system.getInputsVal(sw.pauseCountdownTimerSw) -- Timer hält an, wenn Startschalter aus ist local resetTimerCountdown = system.getInputsVal(sw.resetCountdownTimerSw) local statsTimeVal = system.getInputsVal(sw.statsTimeSw) local flightVal = system.getInputsVal(sw.flightSw) -- Drosselknüppel local an3Val = system.getInputsVal(sw.an3Sw) local an4Val = system.getInputsVal(sw.an4Sw) engine = system.getInputsVal(sw.engineSw) -- Motorfreigabe local timeMil = system.getTimeCounter() -- Systemzeit im ms einlesen local bMotorReleased = not engine or engine > 0 local bMotorRuns = false if flightVal and ((flightVal * 100) >= se.timeTh) and bMotorReleased then bMotorRuns = true end -- Wandeln der Schaltereingaben in boolsche Werte: true = Schalter ist eingeschaltet (in Position, die eingestellt wurde) local bStartFlightTimer = not startFlightTimer or startFlightTimer > 0 local bPauseFlightTimer = not pauseFlightTimer or pauseFlightTimer > 0 local bResetFlightTimer = not resetFlightTimer or resetFlightTimer > 0 local bResetMotorTimer = not resetMotorTimer or resetMotorTimer > 0 local bStartTimerCountdown = not startTimerCountdown or startTimerCountdown > 0 local bPauseTimerCountdown = not pauseTimerCountdown or pauseTimerCountdown > 0 local bResetTimerCountdown = not resetTimerCountdown or resetTimerCountdown > 0 --------------------- -- Timer Motorzeit -- --------------------- if bResetMotorTimer then if (timeVars.eTime) then timeVars.eTime = nil if not se.TimerZeitSpeichern then -- Kein Abspeichern der Zeiten timeVars.eLastTime = timeMil end timeHMS.eMin, timeHMS.eSec = 0, 0 variables.Sensors[variables.MotorTimeIdx].valSec = timeHMS.eSec variables.Sensors[variables.MotorTimeIdx].valMin = timeHMS.eMin end elseif ((not statsTimeVal or statsTimeVal > 0) and bMotorRuns ) then if (not timeVars.eTime) then timeVars.eLastTime = timeMil timeVars.eTime = 0 end local time = timeMil - timeVars.eLastTime if (time >= 1000) then timeVars.eLastTime = timeMil timeVars.eTime = timeVars.eTime + time/1000 timeHMS.eMin = math.floor(timeVars.eTime/60) timeHMS.eSec = timeVars.eTime - timeHMS.eMin*60 variables.Sensors[variables.MotorTimeIdx].valSec = timeHMS.eSec variables.Sensors[variables.MotorTimeIdx].valMin = timeHMS.eMin end else timeVars.eLastTime = timeMil end -------------------- -- Timer Flugzeit -- -------------------- if (bStartFlightTimer or bMotorRuns) and not variables.bFlugzeitLaeft then -- soll gestartet werden variables.bFlugzeitLaeft = true --timeVars.fTime = 0 end if bResetFlightTimer then variables.bFlugzeitLaeft = false if (timeVars.fTime) then timeVars.fTime = nil if not se.TimerZeitSpeichern then -- Kein Abspeichern der Zeiten timeVars.fLastTime = timeMil end timeHMS.fHrs, timeHMS.fMin, timeHMS.fSec = 0, 0, 0 variables.Sensors[variables.FlightTimeIdx].valSec = timeHMS.fSec variables.Sensors[variables.FlightTimeIdx].valMin = timeHMS.fMin variables.Sensors[variables.FlightTimeIdx].valHour = timeHMS.fHrs end elseif variables.bFlugzeitLaeft then if bPauseFlightTimer then timeVars.fLastTime = timeMil end if (not timeVars.fTime) then timeVars.fLastTime = timeMil timeVars.fTime = 0 end if (timeVars.fTime) then local time = timeMil - timeVars.fLastTime if (time >= 1000) then timeVars.fLastTime = timeMil timeVars.fTime = timeVars.fTime + time/1000 timeHMS.fHrs = math.floor(timeVars.fTime/3600) timeHMS.fMin = math.floor(timeVars.fTime/60) % 60 timeHMS.fSec = timeVars.fTime % 60 variables.Sensors[variables.FlightTimeIdx].valSec = timeHMS.fSec variables.Sensors[variables.FlightTimeIdx].valMin = timeHMS.fMin variables.Sensors[variables.FlightTimeIdx].valHour = timeHMS.fHrs end if (an4Val == 1 and lastAn4 < timeMil) then lastAn4 = timeMil + timeAlert local ceil = math.ceil(timeVars.fTime) if (math.abs(ceil) < 60) then system.playNumber(ceil < 0 and -timeHMS.fSec or timeHMS.fSec, 0, "s") elseif (math.abs(ceil) < 3600) then system.playNumber(ceil < 0 and -timeHMS.fMin or timeHMS.fMin, 0, "min") system.playNumber(timeHMS.fSec, 0, "s") else system.playNumber(ceil < 0 and -timeHMS.fHrs or timeHMS.fHrs, 0, "h") system.playNumber(timeHMS.fHrs, 0, "min") system.playNumber(timeHMS.fSec, 0, "s") end end end else timeVars.fLastTime = timeMil end --------------------- -- Timer Countdown -- --------------------- if bResetTimerCountdown and (bStartTimerCountdown or bMotorRuns) then if (timeVars.cTime) then timeVars.cTime = nil timeHMS.cMin, timeHMS.cSec = se.countdownMin, se.countdownSec variables.Sensors[variables.CountdownTimeIdx].valSec = timeHMS.cSec variables.Sensors[variables.CountdownTimeIdx].valMin = timeHMS.cMin end else if not bPauseTimerCountdown and (bStartTimerCountdown or bMotorRuns) then -- Countdown Timer läuft if (not timeVars.cTime) then timeVars.cLastTime = timeMil timeVars.cTime = 60*se.countdownMin + se.countdownSec system.playFile("Timer Start.wav") lastAn3 = timeMil + timeAlert end local time = timeMil - timeVars.cLastTime if (time >= 1000) then timeVars.cLastTime = timeMil timeVars.cTime = timeVars.cTime - time/1000 local ceil = math.ceil(timeVars.cTime) local abs = math.abs(ceil) timeHMS.cMin = math.floor(abs/60) timeHMS.cSec = abs - timeHMS.cMin*60 -- aktuelle Daten an den internen Sendersensor weiterleiten variables.Sensors[variables.CountdownTimeIdx].valSec = timeHMS.cSec variables.Sensors[variables.CountdownTimeIdx].valMin = timeHMS.cMin -- Grenzwerte auswerten und ggf. reagieren if (lastAn3 < timeMil) then if (ceil == 60) then system.playNumber(1, 0, "min") lastAn3 = timeMil + timeAlert elseif (ceil == 30 or ceil == 20 or ceil == 10) then system.playNumber(ceil, 0, "s") lastAn3 = timeMil + timeAlert end if (ceil == 0) then if (se.timerSound == "") then system.playNumber(ceil, 0, "s") else system.playFile(se.timerSound, AUDIO_IMMEDIATE) end lastAn3 = timeMil + timeAlert if (se.vibrates) then system.vibration(false, 4) system.vibration(true, 4) end end end end else timeVars.cLastTime = timeMil end if (timeVars.cTime and an3Val == 1 and lastAn3 < timeMil) then lastAn3 = timeMil + timeAlert local ceil = math.ceil(timeVars.cTime) if (math.abs(ceil) < 60) then system.playNumber(ceil < 0 and -timeHMS.cSec or timeHMS.cSec, 0, "s") else system.playNumber(ceil < 0 and -timeHMS.cMin or timeHMS.cMin, 0, "min") system.playNumber(timeHMS.cSec, 0, "s") end end end ---------------------- -- Motorüberwachung -- ---------------------- if (engine and engine <= 0 and (flightVal and ((flightVal * 100) >= se.timeTh))) then alert = true if (lastAlert < timeMil) then lastAlert = timeMil + timeAlert if (se.vibrate) then system.vibration(false, 4) system.vibration(true, 4) end if (se.monitorSound ~= "") then system.playFile(se.monitorSound, AUDIO_IMMEDIATE) end end else alert = nil lastAlert = 0 end ---------------- -- Timer Beep -- ---------------- if ( (resetTimerBeep == 1) and (not bTimerBeepRuns) ) then if (timeVars.bTime ~= nil) then -- Timer Beep zurücksetzen, wenn er läuft timeVars.bTime = nil timeHMS.bMin, timeHMS.bSec = se.beepMin, se.beepSec variables.Sensors[variables.TimerBeepIdx].valSec = timeHMS.bSec variables.Sensors[variables.TimerBeepIdx].valMin = timeHMS.bMin end end end -------------------------------------------------------------------------- -- Hilfsfunktion: verzoegerte Einmal-Alarmierung per Sounddatei -- -- Kapselt das wiederkehrende Muster aus der Vorlage: -- - Messwert im Alarmbereich? -> Verzoegerungstimer starten/laufen lassen -- - Verzoegerung abgelaufen -> genau EINMAL eine Sounddatei abspielen -- - Messwert wieder im gruenen Bereich -> Timer & "schon gespielt"-Merker -- zuruecksetzen, bereit fuer naechsten Alarm -- -- Parameter: -- alarmActive bool aktueller Alarmzustand (true = Grenzwert unterschritten) -- timeVars table Container der Zeitstufen (== timeVars aus dem Aufrufer) -- timeKey string Feldname der Zeitstufe in timeVars, z.B. "qTime1" -- delayMs number Verzoegerungszeit in ms -- nowMs number aktueller Zeitstempel (== timeMil aus dem Aufrufer) -- display table Container der "Sound schon gespielt"-Merker -- semaKey string Feldname des Merkers in display, z.B. "SemaphoreQ1" -- soundFile string|nil abzuspielende Datei; nil/"" => kein Sound -------------------------------------------------------------------------- local function delayedAlarmSound(alarmActive, timeVars, timeKey, delayMs, nowMs, display, semaKey, soundFile) if not alarmActive then -- Wert wieder im gruenen Bereich -> alles zuruecksetzen/ausschalten timeVars[timeKey] = 0 display[semaKey] = false return end local delayEnd = timeVars[timeKey] if delayEnd == 0 then -- Alarm gerade erst erkannt -> Verzoegerungszeit setzen/starten timeVars[timeKey] = nowMs + delayMs elseif nowMs > delayEnd and not display[semaKey] then -- Verzoegerungszeit abgelaufen und Sound in diesem Alarmzyklus -- noch nicht gespielt -> jetzt genau einmal abspielen if soundFile and soundFile ~= "" then system.playFile(soundFile, AUDIO_QUEUE) end display[semaKey] = true -- verhindert wiederholtes Abspielen end end local function loop() SnapShot = system.getInputsVal(sw.SnapShotSw) switchTiles = system.getInputsVal(sw.switchTilesSw) local startFlightTimer = system.getInputsVal(sw.startFlightTimerSw) local resetTeleVal = system.getInputsVal(sw.resetTeleSw) local resetStatsVal = system.getInputsVal(sw.resetStatsSw) local varihoheVal = system.getInputsVal(sw.varihoheSw) local flightVal = system.getInputsVal(sw.flightSw) local timeMil = system.getTimeCounter() local iActTime = system.getTime() if (timeMil > (variables.iLimitWatchStart + variables.iLimitWatchTime)) and not variables.bLimitWatchReleased then -- Verzögerungszeit ist abgelaufen --> Überwachungen scharf geschaltet variables.bLimitWatchReleased = true end setButtons() setTimers() local SensorWert = nil -- MTAG-Daten lesen -- Ist der richtige Sensor zugewiesen? if(variables.MTAG.iSensorID ~= nil) then if ( (string.find(variables.MTAG.sSensorName, "MTAG") ~= nil) and (variables.MTAG.iSensorID > 1) ) then -- Sensor ist zugewiesen -> Daten einlesen local Value SensorWert = system.getSensorByID( variables.MTAG.iSensorID, 1) if SensorWert ~= nil then Value = SensorWert.value if Value ~= nil then variables.MTAG.iAkkuID = Value end end SensorWert = system.getSensorByID( variables.MTAG.iSensorID, 2) if SensorWert ~= nil then Value = SensorWert.value if Value ~= nil then variables.MTAG.iCapacity = Value end end SensorWert = system.getSensorByID( variables.MTAG.iSensorID, 3) if SensorWert ~= nil then Value = SensorWert.value if Value ~= nil then variables.MTAG.iCycles = Value end end SensorWert = system.getSensorByID( variables.MTAG.iSensorID, 4) if SensorWert ~= nil then Value = SensorWert.value if Value ~= nil then variables.MTAG.iAccOfCells = Value end end SensorWert = system.getSensorByID( variables.MTAG.iSensorID, 5) if SensorWert ~= nil then Value = SensorWert.value if Value ~= nil then variables.MTAG.iCrate = Value end end SensorWert = system.getSensorByID( variables.MTAG.iSensorID, 6) if SensorWert ~= nil then Value = SensorWert.value if Value ~= nil then variables.MTAG.iState = Value end end end end -- GPS-Daten lesen -- Ist der richtige Sensor zugewiesen? if(variables.GPS.iSensorID ~= nil) then if ( (string.find(variables.GPS.sSensorName, "GPS") ~= nil) and (variables.GPS.iSensorID > 1) ) then -- Sensor ist zugewiesen -> Daten einlesen local Value SensorWert = system.getSensorByID( variables.GPS.iSensorID, variables.GPS.iLatParamNo - 1) if SensorWert ~= nil then Value = SensorWert.valGPS if Value ~= nil then variables.GPS.Breite = Value end Value = SensorWert.decimals if Value ~= nil then variables.GPS.iLatNachkomma = Value end end SensorWert = system.getSensorByID( variables.GPS.iSensorID, variables.GPS.iLonParamNo - 1) if SensorWert ~= nil then Value = SensorWert.valGPS if Value ~= nil then variables.GPS.Laenge = Value end Value = SensorWert.decimals if Value ~= nil then variables.GPS.iLonNachkomma = Value end end end end -- Virtuellen Sensor berechnen -- Sind zwei der Sensoren zugewiesen? if ( (variables.ViS.iSensorIDA > 1) and (variables.ViS.iSensorIDB > 1) ) then local SensorWertA, SensorWertB -- Sensortabellen laden if variables.ViS.iSensorTypeA == 2 then SensorWertA = variables.Sensors[variables.ViS.iParamIdxA] else SensorWertA = system.getSensorByID( variables.ViS.iSensorIDA, variables.ViS.iParamNoA - 1) end if variables.ViS.iSensorTypeB == 2 then SensorWertB = variables.Sensors[variables.ViS.iParamIdxB] else SensorWertB = system.getSensorByID( variables.ViS.iSensorIDB, variables.ViS.iParamNoB - 1) end -- Sind Werte vorhanden? if ( (SensorWertA ~= nil) and (SensorWertB ~= nil) ) then -- Ist eine Operation definiert? if (variables.ViS.iOperation > 0) then --Werte zuordnen variables.ViS.fValueA = SensorWertA.value variables.ViS.fValueB = SensorWertB.value if(variables.ViS.iOperation == 1) then -- Mulitiplikation variables.ViS.fValue = variables.ViS.fValueA * variables.ViS.fValueB elseif((variables.ViS.iOperation == 2) and (variables.ViS.fValueB ~= 0.0)) then -- Division variables.ViS.fValue = variables.ViS.fValueA / variables.ViS.fValueB elseif(variables.ViS.iOperation == 3) then -- Addition variables.ViS.fValue = variables.ViS.fValueA + variables.ViS.fValueB elseif(variables.ViS.iOperation == 4) then -- Subtraktion variables.ViS.fValue = variables.ViS.fValueA - variables.ViS.fValueB else variables.ViS.fValue = 0.0 end -- Ergebnis dem Sensorwert zuordnen variables.Sensors[variables.TxVirtualSensor].value = variables.ViS.fValue end end end -- Start der Audioansage der Säulendiagramme (Geber einlesen) -- ---------------------------------------------------------- local switch1 = system.getInputsVal(SpecTiles.AkkuTank.swValPlay1) local switch2 = system.getInputsVal(SpecTiles.AkkuTank.swValPlay2) -- Säulendiagramm 1 if switch1 ~= nil then if switch1 == 1 then SpecTiles.AkkuTank.bCommandPlay1 = true end end -- Säulendiagramm 2 if switch2 ~= nil then if switch2 == 1 then SpecTiles.AkkuTank.bCommandPlay2 = true end end -- Start der Audioansage der TeleValues (Geber einlesen) -- ----------------------------------------------------- local idx for idx=1, ACC_OF_TELEVALUES do local Idx = string.format("iTVInst%d", idx) local tv = TelVal[Idx] if tv.swValPlay ~= nil then local switch = system.getInputsVal(tv.swValPlay) if switch ~= nil then if switch == 1 then tv.bCommandPlay = true end end end end if (resetTeleVal == 1) then minval = 100 maxval = 0 -- Werte der TelVals zurücksetzen local i, idx for i =1, ACC_OF_TELEVALUES do idx = string.format("iTVInst%d", i) TelVal[idx]["fTelValMin"] = TelVal[idx]["fTelValAct"] TelVal[idx]["fTelValMax"] = TelVal[idx]["fTelValAct"] end end if (val) then if (val < minval) then minval = val end if (val > maxval) then maxval = val end end if (resetStatsVal == 1) then variables.Collect.flightsTotal = se.flightsReset variables.Collect.flightsToday = 0 variables.Sensors[variables.FightsIdx].valTotal = variables.Collect.flightsTotal variables.Sensors[variables.FightsIdx].valToday = variables.Collect.flightsToday end -- Empfängertelemetrie im Sender auslesen local txTel = system.getTxTelemetry() if (txTel) then variables.Sensors[variables.TxVoltage].value = txTel.txVoltage variables.Sensors[variables.TxPercent].value = txTel.txBattPercent variables.Sensors[variables.TxCurrent].value = txTel.txCurrent variables.Sensors[variables.TxCapacity].value = txTel.txCapacity local resetRxVal = system.getInputsVal(sw.resetRxSw) local statsFlightVal = system.getInputsVal(sw.statsFlightSw) if (resetRxVal == 1) then setLimits() end rx.values[ 7] = txTel.rx1Percent or 0 rx.values[ 8] = txTel.rx2Percent or 0 rx.values[ 9] = txTel.rxBPercent or 0 rx.values[10] = txTel.rx1Voltage or 0 rx.values[11] = txTel.rx2Voltage or 0 rx.values[12] = txTel.rxBVoltage or 0 for i=1, rx.count do if (i <= 6) then rx.values[i] = txTel.RSSI[i] or 0 if (rx.values[i] > 6) then rx.limits[-i] = true end elseif (i <= 9) then if (rx.values[i] > 90) then rx.limits[-i] = true end end if (rx.limits[-i] and rx.limits[i] > rx.values[i]) then rx.limits[i] = rx.values[i] end end if (rx.values[7] > 1 or rx.values[8] > 1 or rx.values[9] > 1) then if (flightTime) then if (not statsFlightVal or statsFlightVal > 0) then if (not flightDone and timeMil - flightTime >= 120000) then setFlights() flightDone = true variables.Collect.flightsTotal = variables.Collect.flightsTotal + 1 variables.Collect.flightsToday = variables.Collect.flightsToday + 1 variables.Sensors[variables.FightsIdx].valTotal = variables.Collect.flightsTotal variables.Sensors[variables.FightsIdx].valToday = variables.Collect.flightsToday end else if (not flightDone) then flightTime = nil flightLast = nil end end else if (not statsFlightVal or statsFlightVal > 0) then flightTime = timeMil flightDone = nil flightLast = nil end end else if (flightTime) then if (flightLast) then if (timeMil - flightLast > se.TimeDelay * 1000) then flightTime = nil flightDone = nil flightLast = nil end else if (flightDone) then flightTime = nil flightDone = nil flightLast = nil else flightLast = timeMil end end end end --------------------------------- -- Empfängerüberwachung -- REX -- --------------------------------- -- print(string.format("Rx1: U=%dV Q=%d%% A1=%d A2=%d", txTel.rx1Voltage, txTel.rx1Percent, txTel.RSSI[1], txTel.RSSI[2])) -- print(string.format("Rx2: U=%dV Q=%d%% A1=%d A2=%d", txTel.rx2Voltage, txTel.rx2Percent, txTel.RSSI[3], txTel.RSSI[4])) -- print(string.format("bup: U=%dV Q=%d%% A1=%d A2=%d", txTel.rxBVoltage, txTel.rxBPercent, txTel.RSSI[5], txTel.RSSI[6])) local Wert = TelVal["iTVInst1"].fTelValAct -- Zum Testen -- Lokale Referenzen: vermeiden mehrfache Tabellen-Traversierung -- "variables.Rex.Selected.X" / "variables.Rex.Display.X" pro Zyklus local sel = variables.Rex.Selected local disp = variables.Rex.Display if txTel.rx1Voltage > 0 then ---------------------------------------------- -- Empfänger 1 ist eingeschaltet -> überwachen ---------------------------------------------- -- Empfangsqualität delayedAlarmSound( txTel.rx1Percent <= sel.Qlimit, timeVars, "qTime1", sel.Qtime, timeMil, disp, "SemaphoreQ1", sel.SoundQ ) -- Qualität der Antenne A1 local soundA1 if sel.SoundA1A2 ~= "" then -- Kombi-Sound konfiguriert: nur abspielen, wenn Antenne A2 zu diesem -- Zeitpunkt BEREITS im Alarmzustand ist -- sonst bewusst KEIN Einzel-Sound soundA1 = disp.SemaphoreA21 and sel.SoundA1A2 or nil else soundA1 = sel.SoundA1 end delayedAlarmSound( getRSSI(txTel.RSSI[1]) <= sel.A1limit, timeVars, "a1Time1", sel.A1time, timeMil, disp, "SemaphoreA11", soundA1 ) -- Qualität der Antenne A2 local soundA2 if sel.SoundA1A2 ~= "" then -- Kombi-Sound konfiguriert: nur abspielen, wenn Antenne A1 zu diesem -- Zeitpunkt BEREITS im Alarmzustand ist -- sonst bewusst KEIN Einzel-Sound soundA2 = disp.SemaphoreA11 and sel.SoundA1A2 or nil else soundA2 = sel.SoundA2 end delayedAlarmSound( getRSSI(txTel.RSSI[2]) <= sel.A2limit, timeVars, "a2Time1", sel.A2time, timeMil, disp, "SemaphoreA21", soundA2 ) elseif txTel.rx2Voltage > 0 then ---------------------------------------------- -- Empfänger 2 ist eingeschaltet -> überwachen ---------------------------------------------- -- Empfangsqualität delayedAlarmSound( txTel.rx2Percent <= sel.Qlimit, timeVars, "qTime2", sel.Qtime, timeMil, disp, "SemaphoreQ2", sel.SoundQ ) -- Qualität der Antenne A1 local soundA1 if sel.SoundA1A2 ~= "" then soundA1 = disp.SemaphoreA22 and sel.SoundA1A2 or nil else soundA1 = sel.SoundA1 end delayedAlarmSound( getRSSI(txTel.RSSI[3]) <= sel.A1limit, timeVars, "a1Time2", sel.A1time, timeMil, disp, "SemaphoreA12", soundA1 ) -- Qualität der Antenne A2 local soundA2 if sel.SoundA1A2 ~= "" then soundA2 = disp.SemaphoreA12 and sel.SoundA1A2 or nil else soundA2 = sel.SoundA2 end delayedAlarmSound( getRSSI(txTel.RSSI[4]) <= sel.A2limit, timeVars, "a2Time2", sel.A2time, timeMil, disp, "SemaphoreA22", soundA2 ) elseif txTel.rxBVoltage > 0 then --------------------------------------------------- -- Backup-Empfänger ist eingeschaltet -> überwachen --------------------------------------------------- -- Empfangsqualität delayedAlarmSound( txTel.rx2Percent <= sel.Qlimit, timeVars, "qTimeB", sel.Qtime, timeMil, disp, "SemaphoreQB", sel.SoundQ ) -- Qualität der Antenne A1 local soundA1 if sel.SoundA1A2 ~= "" then soundA1 = disp.SemaphoreA2B and sel.SoundA1A2 or nil else soundA1 = sel.SoundA1 end delayedAlarmSound( getRSSI(txTel.RSSI[5]) <= sel.A1limit, timeVars, "a1TimeB", sel.A1time, timeMil, disp, "SemaphoreA1B", soundA1 ) -- Qualität der Antenne A2 local soundA2 if sel.SoundA1A2 ~= "" then soundA2 = disp.SemaphoreA1B and sel.SoundA1A2 or nil else soundA2 = sel.SoundA2 end delayedAlarmSound( getRSSI(txTel.RSSI[6]) <= sel.A2limit, timeVars, "a2TimeB", sel.A2time, timeMil, disp, "SemaphoreA2B", soundA2 ) else -- Kein Empfänger hat Spannung -- Alle Sperren zurücksetzen disp.SemaphoreQ1 = false disp.SemaphoreA11 = false disp.SemaphoreA21 = false disp.SemaphoreQ2 = false disp.SemaphoreA12 = false disp.SemaphoreA22 = false disp.SemaphoreQB = false disp.SemaphoreA1B = false disp.SemaphoreA2B = false timeVars.qTime1 = 0 timeVars.a1Time1 = 0 timeVars.a2Time1 = 0 timeVars.qTime2 = 0 timeVars.a1Time2 = 0 timeVars.a2Time2 = 0 timeVars.qTimeB = 0 timeVars.a1TimeB = 0 timeVars.a2TimeB = 0 end -- Empfängerüberwachung ende end if (timeMil - timeVars.gpsTime >= 3000) then timeVars.gpsTime = timeMil end -- Vorflug Akkuspannungscheck -- Spannungssensor einlesen if (variables.Vor.iSensorID ~= nil) then if variables.Vor.iSensorID > 1 then -- Sensor ist zugewiesen -> Daten einlesen variables.Vor.fValue = readSensor(variables.Vor.iSensorType, variables.Vor.iParamIdx, variables.Vor.iSensorID, variables.Vor.iSensorNo) end else variables.Vor.fValue = 0.0 end if (variables.Vor.fValue == 0.0) then if (batteryAlert) then batteryAlert = nil end elseif (se.vorflugvolt > 0 and variables.Vor.fValue * 10 >= se.vorflugvolt) then if (batteryAlert ~= 0) then batteryAlert = 0 end else if (batteryAlert) then if (batteryAlert < 0) then if (timeMil >= -batteryAlert and se.vorflugvolt > 0 and variables.Vor.fValue * 10 < se.vorflugvolt) then batteryAlert = timeMil + 20000 system.playBeep(4, 3000, 400) if (se.vibrate) then system.vibration(false, 4) system.vibration(true , 4) end end elseif (batteryAlert > 0) then if (timeMil >= batteryAlert) then batteryAlert = 0 end end else batteryAlert = -(timeMil + se.vorflugzeit * 1000) end end if (varihoheVal == 1) then local current local height -- Die Höhen-Werte aus einem TeleValue oder Säulendiagramm holen if (variables.Ans.iValueNoAnsageHoeheMeter > 1) and (variables.Ans.iValueNoAnsageHoeheMeter < (ACC_OF_TELEVALUES + 3)) then -- Wert im gültigen Bereich if variables.Ans.iValueNoAnsageHoeheMeter < (ACC_OF_TELEVALUES + 2) then local Idx = string.format("iTVInst%d", variables.Ans.iValueNoAnsageHoeheMeter-1) -- TeleValue height = TelVal[Idx].fTelValAct elseif variables.Ans.iValueNoAnsageHoeheMeter == (ACC_OF_TELEVALUES + 2) then -- Säulendiagramm 1 height = SpecTiles.AkkuTank.fValueAct1 elseif variables.Ans.iValueNoAnsageHoeheMeter == (ACC_OF_TELEVALUES + 3) then -- Säulendiagramm 2 height = SpecTiles.AkkuTank.fValueAct2 end else height = 0.0 end -- Die Strom-Werte aus einem TeleValue oder Säulendiagramm holen if (variables.Ans.iValueNoAnsageHoeheMotorStrom > 1) and (variables.Ans.iValueNoAnsageHoeheMotorStrom < (ACC_OF_TELEVALUES + 3)) then -- Wert im gültigen Bereich if variables.Ans.iValueNoAnsageHoeheMotorStrom < (ACC_OF_TELEVALUES + 2) then local Idx = string.format("iTVInst%d", variables.Ans.iValueNoAnsageHoeheMotorStrom-1) -- TeleValue current = TelVal[Idx].fTelValAct elseif variables.Ans.iValueNoAnsageHoeheMotorStrom == (ACC_OF_TELEVALUES + 2) then -- Säulendiagramm 1 current = SpecTiles.AkkuTank.fValueAct1 elseif variables.Ans.iValueNoAnsageHoeheMotorStrom == (ACC_OF_TELEVALUES + 3) then -- Säulendiagramm 2 current = SpecTiles.AkkuTank.fValueAct2 end else current = 0.0 end if (se.lastHeight) then local mode = se.mitohne local step = se.gehohe local rise = se.rise local diff = height - se.lastHeight local amp = se.risea if (math.abs(diff) > step) then se.lastHeight = height if (not rise or current <= amp) then if (diff > 0 and mode ~= 2 or diff < 0 and mode ~= 1) then system.playNumber(height, 0, "m") end end end else se.lastHeight = height end end if (timeVars.timeModel) then if (timeMil >= timeVars.timeModel) then timeVars.timeModel = nil if (se.alarmVoice4 ~= "") then system.playFile(se.alarmVoice4, AUDIO_QUEUE) end end end -- Schnapschuß ausführen? if (SnapShot == 1) then -- Nur bei kommend wird geschrieben if (variables.SnapShot.Done == false) then writeSnapShot() variables.SnapShot.Done = true -- Bei Aufrif der Projektierung wird die zuletzt aufgenommene Datei angezeigt. variables.SnapShot.FileFirstTime = true -- Bei Aufruf der Projektierung wird die zuletzt aufgenommene Datei angezeigt. end else -- Es darf ein neuer Schnapschuß ausgeführt werden variables.SnapShot.Done = false end -- Die Cala-App Daten dem Sensorenfeld zuordnen -- Falls die Calca App V5.0 arbeitet: if( (Calca_dispGas ~= nil) or (Calca_selTank ~= nil) or (Calca_capacity ~= nil) or (Calca_dispFuel ~= nil) ) then variables.Sensors[variables.GasIdx].value = Calca_dispGas variables.Sensors[variables.SelectedIdx].value = Calca_selTank variables.Sensors[variables.CapacityIdx].value = Calca_capacity variables.Sensors[variables.FuelIdx].value = Calca_dispFuel end -- Falls die calca-Elec App ab v7.6 arbeitet: if(SpecTiles.calcaElec ~= nil) then variables.Sensors[variables.Capacity70Idx].value = SpecTiles.calcaElec.batteryCapacity variables.Sensors[variables.remCapaIdx].value = SpecTiles.calcaElec.remainingPercent variables.Sensors[variables.consCapaIdx].value = SpecTiles.calcaElec.consumedCapacity variables.Sensors[variables.AlarmIdx].value = SpecTiles.calcaElec.mainAlarmPercent variables.Sensors[variables.preAlarmIdx].value = SpecTiles.calcaElec.preAlarmPercent if(SpecTiles.calcaElec.actualCurrent ~= nil) and (variables.actualCurrentIdx > 0) then variables.Sensors[variables.actualCurrentIdx].value = SpecTiles.calcaElec.actualCurrent end end -- Falls die calca-Fuel App ab v1.6 arbeitet: if(SpecTiles.calcaFuel ~= nil) then variables.Sensors[variables.tankCapacityIdx].value = SpecTiles.calcaFuel.tankCapacity variables.Sensors[variables.fuelremPercentIdx].value = SpecTiles.calcaFuel.remainingPercent variables.Sensors[variables.fuelmainAlarmPercentIdx].value = SpecTiles.calcaFuel.mainAlarmPercent variables.Sensors[variables.fuelPreAlarmPercentIdx].value = SpecTiles.calcaFuel.preAlarmPercent variables.Sensors[variables.fuelUsedIdx].value = SpecTiles.calcaFuel.fuelUsed variables.Sensors[variables.fuelFlowIdx].value = SpecTiles.calcaFuel.fuelFlow end -- Falls die calca-Plus App ab v5.8 arbeitet: if(SpecTiles.calcaPlus ~= nil) then variables.Sensors[variables.plusCapacityIdx].value = SpecTiles.calcaPlus.batteryCapacity variables.Sensors[variables.plusCapacity1Idx].value = SpecTiles.calcaPlus.batteryCapacity1 variables.Sensors[variables.plusCapacity2Idx].value = SpecTiles.calcaPlus.batteryCapacity2 variables.Sensors[variables.plusCRate1Idx].value = SpecTiles.calcaPlus.batteryCRate1 variables.Sensors[variables.plusCRate2Idx].value = SpecTiles.calcaPlus.batteryCRate2 variables.Sensors[variables.plusCRateDynIdx].value = SpecTiles.calcaPlus.batteryCRateDyn variables.Sensors[variables.plusremPercentIdx].value = SpecTiles.calcaPlus.remainingPercent variables.Sensors[variables.plusconCapacityIdx].value = SpecTiles.calcaPlus.consumedCapacity variables.Sensors[variables.plusActualCurrentIdx].value = SpecTiles.calcaPlus.actualCurrent variables.Sensors[variables.plusUSmoothIdx].value = SpecTiles.calcaPlus.uSmooth variables.Sensors[variables.plusBatteryTempCoreIdx].value = SpecTiles.calcaPlus.batteryTempCore variables.Sensors[variables.plusPreAlarmPercentIdx].value = SpecTiles.calcaPlus.mainAlarmPercent variables.Sensors[variables.plusMainAlarmPercentIdx].value = SpecTiles.calcaPlus.preAlarmPercent end -- Falls die Betriebsstundenzähler ab v0.61 arbeiten: if(SpecTiles.OpAccHour ~= nil) then variables.Sensors[variables.OpAccBZIdx].valMin = tonumber(SpecTiles.OpAccHour.BZ_Min_str) variables.Sensors[variables.OpAccBZIdx].valHour = tonumber(SpecTiles.OpAccHour.BZ_Std_str) variables.Sensors[variables.OpAcctotBZIdx].valMin = tonumber(SpecTiles.OpAccHour.totBZ_Min_str) variables.Sensors[variables.OpAcctotBZIdx].valHour = tonumber(SpecTiles.OpAccHour.totBZ_Std_str) variables.Sensors[variables.OpAcctotFZIdx].valMin = tonumber(SpecTiles.OpAccHour.totFZ_Min_str) variables.Sensors[variables.OpAcctotFZIdx].valHour = tonumber(SpecTiles.OpAccHour.totFZ_Std_str) variables.Sensors[variables.OpAccmodelFZIdx].valMin = tonumber(SpecTiles.OpAccHour.modelFZ_Min_str) variables.Sensors[variables.OpAccmodelFZIdx].valHour = tonumber(SpecTiles.OpAccHour.modelFZ_Std_str) end --Sendersensor Parameter: Uhrzeit mit Datum aktualisieren local dt = system.getDateTime() variables.Sensors[variables.ClockIdx].valSec = dt.sec variables.Sensors[variables.ClockIdx].valMin = dt.min variables.Sensors[variables.ClockIdx].valHour = dt.hour ---------------- -- Timer Beep -- ---------------- local chkTime = 0 local startTimerBeep = system.getInputsVal(sw.startBeepTimerSw) local pauseTimerBeep = system.getInputsVal(sw.pauseBeepTimerSw) local resetTimerBeep = system.getInputsVal(sw.resetBeepTimerSw) local bMotorReleased = not engine or engine > 0 local bMotorRuns = false if flightVal and ((flightVal * 100) >= se.timeTh) and bMotorReleased then bMotorRuns = true end -- Prüfen ob eine TimerBeep-Datei angegeben wurde if (variables.BeepCmd.File ~= "...") then -- Prüfen ob der Timer beep läuft if ( (timeVars.bTime == nil) and (not bTimerBeepRuns) ) then -- Der Timer Bepp läuft nicht -- Wurde er aktiviert? if (startTimerBeep == 1) or bMotorRuns then -- Geber wurde betätigt bTimerBeepRuns = true -- Wenn ein Zustandsfeld geladen wurde -> Zustandsmaschine starten variables.BeepCmd.iState = 1 -- erster Zustand erreicht timeVars.bTime = math.ceil(timeMil/1000) + se.beepMin * 60 + se.beepSec -- Zielzeit setzen -- TimerBeep ist gestartet mit der gesetzten Zielzeit else -- Alle Werte aud Anfang setzen variables.BeepCmd.iState = -1 end else if(timeVars.bTime == nil) then -- Das kann passieren beim neuladen --> Timer zurücksetzen resetTimerBeep = 1 -- Wenn eine Beep-Tabelle gesetzt wurde, Beep Prüfen elseif pauseTimerBeep ~= 1 then if ( (variables.Sensors[variables.TimerBeepIdx].TimerBeepCmd ~= nil) and bTimerBeepRuns ) then -- Ist eine Beepzeit erreicht? chkTime = math.ceil(timeMil/1000) - timeVars.bTime -- + variables.Sensors[variables.TimerBeepIdx].TimerBeepCmd[variables.BeepCmd.iState].Time if (variables.Sensors[variables.TimerBeepIdx].TimerBeepCmd[variables.BeepCmd.iState] ~= nil) then if (chkTime >= variables.Sensors[variables.TimerBeepIdx].TimerBeepCmd[variables.BeepCmd.iState].Time ) then -- Ja beepen local Typ, Cnt, Freq, Length, TxCol, BgCol, File, Vibra Typ = variables.Sensors[variables.TimerBeepIdx].TimerBeepCmd[variables.BeepCmd.iState].Type if (Typ == 1) then Cnt = variables.Sensors[variables.TimerBeepIdx].TimerBeepCmd[variables.BeepCmd.iState].Cnt Freq = variables.Sensors[variables.TimerBeepIdx].TimerBeepCmd[variables.BeepCmd.iState].Freq Length = variables.Sensors[variables.TimerBeepIdx].TimerBeepCmd[variables.BeepCmd.iState].Length system.playBeep(Cnt, Freq, Length) elseif (Typ == 2) then File = variables.Sensors[variables.TimerBeepIdx].TimerBeepCmd[variables.BeepCmd.iState].File system.playFile(File, AUDIO_IMMEDIATE) end if(variables.Sensors[variables.TimerBeepIdx].TimerBeepCmd[variables.BeepCmd.iState].TxCol ~= nil) then variables.Sensors[variables.TimerBeepIdx].valTxColor = variables.Sensors[variables.TimerBeepIdx].TimerBeepCmd[variables.BeepCmd.iState].TxCol end if(variables.Sensors[variables.TimerBeepIdx].TimerBeepCmd[variables.BeepCmd.iState].BgCol ~= nil) then variables.Sensors[variables.TimerBeepIdx].valBgColor = variables.Sensors[variables.TimerBeepIdx].TimerBeepCmd[variables.BeepCmd.iState].BgCol end if (variables.Sensors[variables.TimerBeepIdx].TimerBeepCmd[variables.BeepCmd.iState].Vib ~= nil) then Vibra = variables.Sensors[variables.TimerBeepIdx].TimerBeepCmd[variables.BeepCmd.iState].Vib --[[ o 1 – long pulse o 2 – short pulse o 3 – 2 × short pulse o 4 – 3 × short pulse o Other – stops vibration --]] system.vibration(Vibra & 0x0001, (Vibra >> 1) & 0x000F ); end -- in den nächsten Zustand wechseln variables.BeepCmd.iState = variables.BeepCmd.iState + 1 -- Prüfen, ob der letzte Zustand überschritten wurde if (variables.BeepCmd.iState > #variables.Sensors[variables.TimerBeepIdx].TimerBeepCmd) then -- Zustandsmaschine abschalten variables.BeepCmd.iState = 0 bTimerBeepRuns = false end end -- Beep Min und Sec setzen chkTime = -chkTime timeHMS.bMin = math.floor(chkTime / 60) timeHMS.bSec = chkTime - (timeHMS.bMin * 60) else system.messageBox(trans.Msg_BeepTimerCMDfile, 2) end else variables.Sensors[variables.TimerBeepIdx].valTxColor = nil variables.Sensors[variables.TimerBeepIdx].valBgColor = nil chkTime = math.ceil(timeMil/1000) - timeVars.bTime timeHMS.bMin = math.floor(chkTime / 60) timeHMS.bSec = chkTime - (timeHMS.bMin * 60) variables.Sensors[variables.TimerBeepIdx].valSign = true variables.Sensors[variables.TimerBeepIdx].valTxColor = 23 -- Rot end end -- Weiterleiten für Ausgabe variables.Sensors[variables.TimerBeepIdx].valSec = timeHMS.bSec variables.Sensors[variables.TimerBeepIdx].valMin = timeHMS.bMin end end -- Timer Beep beenden und alle Werte zurücksetzen if (resetTimerBeep == 1) then bTimerBeepRuns = false variables.BeepCmd.iState = -1 timeVars.bTime = nil timeHMS.bMin = se.beepMin timeHMS.bSec = se.beepSec variables.Sensors[variables.TimerBeepIdx].valSec = timeHMS.bSec variables.Sensors[variables.TimerBeepIdx].valMin = timeHMS.bMin variables.Sensors[variables.TimerBeepIdx].valTxColor = nil variables.Sensors[variables.TimerBeepIdx].valBgColor = nil variables.Sensors[variables.TimerBeepIdx].valSign = false end ----------------- -- Oszilloskop -- ----------------- local i, j local ov = Oszi.Data.Values local Idx, Id local accOfValues = Oszi.Data.Values.maxTime / Oszi.Data.Values.T local value -- Schalter einlesen local startOszi = system.getInputsVal(sw.OsziStartSw) local stoppOszi = system.getInputsVal(sw.OsziStoppSw) local resetOszi = system.getInputsVal(sw.OsziResetSw) local saveOszi = system.getInputsVal(sw.OsziSaveSw) local loadOszi = system.getInputsVal(sw.OsziLoadSw) local oneShotOszi = system.getInputsVal(sw.OsziOneShotSw) -- Scahlter umsetzen in Bool. Wenn der Schalter nicht definiert ist --> false local bStartOszi = (not startOszi or startOszi > 0) and (sw.OsziStartSw ~= nil) local bStoppOszi = (not stoppOszi or stoppOszi > 0) and (sw.OsziStoppSw ~= nil) local bResetOszi = (not resetOszi or resetOszi > 0) and (sw.OsziResetSw ~= nil) local bSaveOszi = (not saveOszi or saveOszi > 0) and (sw.OsziSaveSw ~= nil) local bLoadOszi = (not loadOszi or loadOszi > 0) and (sw.OsziLoadSw ~= nil) local bOneShotOszi = (not oneShotOszi or oneShotOszi > 0) and (sw.OsziOneShotSw ~= nil) if Oszi.Data.oTime == nil then -- Oszi kann gestartet werden if bStartOszi or bOneShotOszi then -- Oszi soll gestartet werden, entweder durch Start oder durch OneShot Oszi.Data.oTime = 0 Oszi.Data.oShotTime = 0 end else if Oszi.Data.oTime == 0 then -- Alte Daten löschen ResetOsziData() -- ersten Abtastzyklus starten Oszi.Data.oTime = timeMil + Oszi.Data.Values.T -- Aktuelle Zeit in ms + Zeit, wenn der Abtastzyklus erreicht ist end if Oszi.Data.oShotTime == 0 and bOneShotOszi and not Oszi.Semaphoren.OneShot then -- OneShot ist nun aktiv Oszi.Semaphoren.OneShot = true -- Endezeit des OneShot setzen Oszi.Data.oShotTime = accOfValues -- Anzahl der Abtastzyklen. Genaue Zeit geht nicht, da die Abtastzyklen ungenau sind end -- Prüfen, ob das Ende der Abtastrate ereicht ist if (timeMil >= Oszi.Data.oTime) and not bStoppOszi then -- Abtastzykluszeitende erreiccht -- Daten für alle Kanäle bearbeiten, neue Daten holen for j=1, Oszi.Data.Values.AccOfChannels do Idx = string.format("Ch%d", j) if ov[Idx].TVpointer ~= nil then -- Diesen Kanal bearbeiten -- Umspeichern -- links nach rechts for i = accOfValues, 2, -1 do for i = 2, accOfValues do -- links nach rechts ov[Idx].Point[i] = ov[Idx].Point[i-1] ov[Idx].Point[i-1] = ov[Idx].Point[i] ov[Idx].Time[i-1] = ov[Idx].Time[i] end -- Neuen Wert eintragen value = 0.0 Id = string.format("iTVInst%d", ov[Idx].TVpointer) if TelVal[Id].fTelValAct ~= nil then value = TelVal[Id].fTelValAct end -- Max-/Minwerte prüfen, je nach Position der X-Achse if Oszi.Graph.posXaxis == 1 then if value > 0.0 then value = 0.0 elseif value < -ov[Idx].maxValue then value = -ov[Idx].maxValue end elseif Oszi.Graph.posXaxis == 2 then if value < -ov[Idx].maxValue then value = -ov[Idx].maxValue elseif value > ov[Idx].maxValue then value = ov[Idx].maxValue end else if value < 0.0 then value = 0.0 elseif value > ov[Idx].maxValue then value = ov[Idx].maxValue end end -- Neuen Wert eintragen -- links nach rechts ov[Idx].Point[1] = value ov[Idx].Point[accOfValues] = value ov[Idx].Time[accOfValues] = string.format("%.0f", timeMil) if Oszi.Data.oShotTime > 0 then -- Der OneShot läuft Oszi.Data.oShotTime = Oszi.Data.oShotTime - 1 end end -- Neuen Zyklus starten Oszi.Data.oTime = timeMil + Oszi.Data.Values.T end else --print(string.format("Oszi.Semaphoren.Save = %s", Oszi.Semaphoren.Save)) -- Das Oszi läuft und der Stopschalter wurde betätigt und keine Speichersperre if bSaveOszi and Oszi.Semaphoren.Save then -- Wiederholtes Speichern sperren Oszi.Semaphoren.Save = false -- Speichern gesperrt --Oszi.Save.Name = string.format("%sOszi_%s_%02d%02d-%02d%02d%02d%s", folderJsn, metaData.Model, dt.mon, dt.day, dt.hour, dt.min, dt.sec, extensionJsonFile) Oszi.Save.Name = string.format("%sOszi_%s%s", folder, metaData.Model, extensionJsonFile) local file = io.open(Oszi.Save.Name, "w+") if not file then return false end -- Datei konnte nicht geöffnet werden -- Aktuelles Datum speichern local dt = system.getDateTime() Oszi.Save.Date = string.format("%02d.%02d.%d %02d:%02d:%02d", dt.day, dt.mon, dt.year, dt.hour, dt.min, dt.sec) Oszi.Data.Values.sStoppText = "SaveSwitch "..trans.menu_OsziControlStopTime..Oszi.Save.Date Oszi.Save.Values = Oszi.Data.Values -- Daten speichern writeLine(file, Oszi.Save) -- Oszi speichern io.close(file) system.messageBox(trans.Msg_Oszisave, 1) -- Stopp ist aufgehoben und Speichersperre ist aktiv elseif not bSaveOszi and not Oszi.Semaphoren.Save then Oszi.Semaphoren.Save = true -- Erneutes Speichern ist freigegeben end end -- Prüfen ob die OneShot Dauer erreicht ist if (Oszi.Data.oShotTime <= 0) and Oszi.Semaphoren.OneShot then -- Das Oszi läuft, der OneShot ist aktiv und die OneShot Zeit ist abgelaufen und der OneShot soll angehalten werden --Oszi.Save.Name = string.format("%sOszi_%s_%02d%02d-%02d%02d%02d%s", folderJsn, metaData.Model, dt.mon, dt.day, dt.hour, dt.min, dt.sec, extensionJsonFile) Oszi.Save.Name = string.format("%sOszi_%s%s", folder, metaData.Model, extensionJsonFile) local file = io.open(Oszi.Save.Name, "w+") if not file then return false end -- Datei konnte nicht geöffnet werden -- Aktuelles Datum speichern local dt = system.getDateTime() Oszi.Save.Date = string.format("%02d.%02d.%d %02d:%02d:%02d", dt.day, dt.mon, dt.year, dt.hour, dt.min, dt.sec) Oszi.Data.Values.sStoppText = "OneShot "..trans.menu_OsziControlStopTime..Oszi.Save.Date Oszi.Save.Values = Oszi.Data.Values -- Daten speichern writeLine(file, Oszi.Save) -- Oszi speichern io.close(file) system.messageBox(trans.Msg_Oszisave, 1) Oszi.Data.oTime = nil -- Zeitstufe sperren Oszi.Data.oShotTime = nil -- Zeitstufe sperren Oszi.Semaphoren.OneShot = false -- OneShot darf wieder ausgelöst werden --bResetOszi = true -- Nun alles zurücksetzen end end -- Erst zum Schluß auf Reset prüfen -- Oszi läuft, prüfen, ob Oszi resettet werden soll if bResetOszi then -- Oszi abschalten und Oszi.Data.oTime = nil Oszi.Data.oShotTime = nil -- alte Daten löschen ResetOsziData() end -- Gespeicherte Daten laden --------------------------- -- Verriegelung prüfen if not bLoadOszi then -- Schalter ist aus und Sperre noch gesetzt --> darf erneut geladen werden Oszi.Semaphoren.Load = true end if bLoadOszi and Oszi.Semaphoren.Load then -- Schalter betätigt und das Laden ist freigegeben -- Oszi abschalten und Oszi.Data.oTime = nil Oszi.Data.oShotTime = nil -- alte Daten löschen ResetOsziData() -- Dateiname ermitteln und lesend öffnen Oszi.Save.Name = string.format("%sOszi_%s%s", folder, metaData.Model, extensionJsonFile) local file = io.open(Oszi.Save.Name, "r") if not file then return false end -- Datei konnte nicht geöffnet werden Oszi.Save = readLine(file) -- Oszilloskop-Daten -- Daten in den Anzeigespeicher übertragen Oszi.Data = Oszi.Save if Oszi.Save == nil then io.close(file) print("Fehler: Ungültiges Dateiformat!") -- Daten wieder in den ursprünglichen Zustand setzen ResetOsziData() end io.close(file) -- Laden sperren --> bei länger betätigtem Schalter ein erneutes Laden sperren Oszi.Semaphoren.Load = false end end -- loop() local function printForm() if bShowColorByPrintForm then lcd.setColor(RGB1, RGB2, RGB3, RGB4) lcd.drawFilledRectangle(0,0,10,236) end end local function init(code) local pLoad, registerForm, registerTelemetry = system.pLoad, system.registerForm, system.registerTelemetry local string_format = string.format local math_floor = math.floor local math_abs = math.abs local sysPLoad = system.pLoad -- Einmalige Ermittelung der Modellspeicherdatei jsnModelFile = system.pLoad("modelfileJSN", nil) if ( jsnModelFile == nil ) then -- Dateiname festlegen local dt = system.getDateTime() jsnModelFile = string.format("%sDApp_%s_%02d%02d-%02d%02d%02d%s", folderJsn, metaData.Model, dt.mon, dt.day, dt.hour, dt.min, dt.sec, extensionJsonFile) system.pSave("modelfileJSN", jsnModelFile) metaData.DataStorage.modelfile = jsnModelFile --print("Modelldateiname festgelegt: "..metaData.DataStorage.modelfile) else metaData.DataStorage.modelfile = jsnModelFile --print("Modelldateiname geladen: "..metaData.DataStorage.modelfile) end sw.startFlightTimerSw = nil sw.pauseFlightTimerSw = nil sw.resetFlightTimerSw = nil sw.startBeepTimerSw = nil sw.pauseBeepTimerSw = nil sw.resetBeepTimerSw = nil sw.startCountdownTimerSw = nil sw.pauseCountdownTimerSw = nil sw.resetCountdownTimerSw = nil sw.resetMotorTimerSw = nil se.vorflugvolt = 0 variables.iActShownTeleValue = 1 -- Aktuell angezeigtes TeleValue bei der Projektierung variables.iActShownFlexPic = 1 -- Aktuell angezeigtes FlexPic bei der Projektierung variables.bLimitWatchReleased = false -- Es soll erst nach einer Pause mit der Grenzwertüberwachung begonnen werden. variables.iLimitWatchTime = 500 -- Verzögerungszeit in Millisekunden variables.iLimitWatchStart = system.getTimeCounter() variables.column = {} variables.column.Left = 0 variables.column.Right = 186 variables.column.Middle = 132 variables.SnapShot = {} variables.SnapShot.Done = false variables.SnapShot.Files = {} variables.SnapShot.Files[1] = "..." variables.SnapShot.FileName = "..." variables.SnapShot.FileIndex = 1 variables.SnapShot.FileEraseName = "..." variables.SnapShot.FileEraseIndex = 1 variables.SnapShot.FileFirstTime = true variables.bSpezialSensorenDetach = false -- Variablen für den MTAG Sensor (Chip am Akku) variables.MTAG = { sSensorName = "...", iSensorNo = 1, iSensorID = 1, iSensorIdx = 1, iSensorType = 1, iBgColor = 28, sAkkuName = {}, iAkkuID = 0, iCapacity = 0, iCycles = 1, iAccOfCells = 2, iCrate = 20, iState = 0, } -- Variablen für den GPS Sensor variables.GPS = { sSensorName = "...", iSensorNo = 1, iSensorID = 1, iSensorIdx = 1, iSensorType = 1, sLatParam = "...", iLatParamNo = 1, iLatParamIdx = 1, sLatEinheit = " ?", iLatNachkomma = 0, sLonParam = "...", iLonParamNo = 1, iLonParamIdx = 1, sLonEinheit = " ?", iLonNachkomma = 1, iBgColor = 34, Breite = 0, Laenge = 0 } -- Variablen für den Virtuellen Sensor (4 Grundrechenarten) variables.ViS = { sSensorNameA = "...", iSensorNoA = 1, iSensorIDA = 1, iSensorIdxA = 1, iSensorTypeA = 1, sParamA = "...", iParamNoA = 1, iParamIdxA = 1, sEinheitA = " ?", iNachkommaA = 0, fValueA = 0.0, sSensorNameB = "...", iSensorNoB = 1, iSensorIDB = 1, iSensorIdxB = 1, iSensorTypeB = 1, sParamB = "...", iParamNoB = 1, iParamIdxB = 1, sEinheitB = " ?", iNachkommaB = 0, fValueB = 0.0, iOperation = 0, fValue = 0.0, unit = " ?" } -- Variablen für die Vorflug-Spannungserfassung variables.Vor = { sSensorName = "", iSensorNo = 1, iSensorID = 0, iSensorIdx = 1, iSensorType = 1, sParam = "", iParamNo = 1, iParamIdx = 1, sEinheit = " ?", iNachkomma = 0, fValue = 0.0 } -- Variablen für die Ansagen der Höhe (Zuordnung von TeleValues und Säulendiagramm als Datenquelle) variables.Ans = { iValueNoAnsageHoeheMeter = 1, -- 1= kein TeleValue zugeordnet iValueNoAnsageHoeheMotorStrom = 1, -- 1= kein TeleValue zugeordnet tabValues = {} } -- Erstinitialisierung der Tabelle variables.Ans.tabValues[1] = "..." for i=2, ACC_OF_TELEVALUES + 1 do variables.Ans.tabValues[i] = string.format("TeleValue%d", i-1) end variables.Ans.tabValues[ACC_OF_TELEVALUES + 2] = trans.drawBarChart.." 1" variables.Ans.tabValues[ACC_OF_TELEVALUES + 3] = trans.drawBarChart.." 2" -- Initialisierung local i local device = system.getDeviceType() if (lcd.height > 240) then heightMax = 237 else heightMax = 159 end se.countdownMin = 10 se.countdownSec = 0 se.vorflugvolt = 0 se.vorflugzeit = 0 se.modellname = 0 se.flightsReset = 0 se.mitohne = 3 se.gehohe = 50 se.beepMin = 4 se.beepSec = 0 se.timeTh = -95 se.risea = 5 se.TimeDelay = 0 se.alarmVoice4 = "" se.monitorSound = "" se.timerSound = "" se.lastHeight = 0 local AT = SpecTiles.AkkuTank -- Lokale Referenz für kürzeren Zugriff -- +++++ Sensordaten laden +++++ -- Sensordaten nun in die zugreifbaren Felder zur Projektierung analysieren und umladen local iAktualSensorID = 0 -- Startwert zum Erkennen des ersten Sensors -- Schleifenvariablen local k = 1 -- Zählung der Sensoren, 1. Sensor k = 2; K = 1 ist Leer-Eintrag local j = 0 -- Zählung der Sensorwerte local zeile, zeileIdx TelVal.Sensors = system.getSensors() -- Sensorstrukturen laden mit den Empfängersensoren for i=1, #TelVal.Sensors do local sensor = TelVal.Sensors[i] local sensorId = sensor["id"] if( sensorId ~= iAktualSensorID ) then k=k+1 j=2 iAktualSensorID = sensorId TelVal.SensorListId[k] = sensorId TelVal.SensorListType[k] = 1 TelVal.SensorListLabel[k] = string_format("Spirit ID: %d", sensorId) if( sensor["param"] == 0 ) then TelVal.SensorListLabel[k] = string_format("%s ID: %d", sensor["label"], sensorId) else zeile = string_format("SensorListWertLabel%d", k-1) TelVal[zeile]["bTelValSensorNoName"] = true TelVal[zeile][j] = sensor["label"] zeileIdx = string_format("SensorListWertLabelIdx%d", k-1) TelVal[zeileIdx][j] = i j=j+1 end TelVal.SensorListIdx[k] = i else zeile = string_format("SensorListWertLabel%d", k-1) TelVal[zeile][j] = sensor["label"] zeileIdx = string_format("SensorListWertLabelIdx%d", k-1) TelVal[zeileIdx][j] = i j=j+1 -- Sonderbehandlungen prüfen if ( (string.find(TelVal.SensorListLabel[k],"BF D1") ~= nil) and (j == 9) ) then zeile = string_format("SensorListWertLabel%d", k-1) TelVal[zeile][j] = "..." zeileIdx = string_format("SensorListWertLabelIdx%d", k-1) TelVal[zeileIdx][j] = i j=j+1 end end end -- Sendersensoren erstellen --------------------------- local iIdx = 0 local iTransmitterSensorID = 1052094324 -- Jeti DC24 <--> J(10)e(5)t(20)i(9) D(4)C(3)24 variables.Sensors = {} -- Variablen für Flugzeit Timer variables.bFlugzeitLaeft = false variables.TxSensIdx = 0 -- Feldpositionen im Sensorfeld des neuen Sendersensors variables.FightsIdx = 0 variables.FlightTimeIdx = 0 variables.CountdownTimeIdx = 0 variables.MotorTimeIdx = 0 variables.ClockIdx = 0 variables.TimerBeepIdx = 0 variables.TxVirtualSensor = 0 variables.TxVoltage = 0 variables.TxPercent = 0 variables.TxCurrent = 0 variables.TxCapacity = 0 -- Daten für den Timer Beep variables.BeepCmd = {} variables.BeepCmd.FileList = {"..."} variables.BeepCmd.iFileListIdx = 1 variables.BeepCmd.File = "..." -- *.jsn variables.BeepCmd.iState = 0 -- Zustand für die Zustandsmaschine variables.BeepCmd.File = sysPLoad("BeepCmdFile", variables.BeepCmd.File) variables.BeepCmd.iFileListIdx = sysPLoad("BeepCmdFileIdx", variables.BeepCmd.iFileListIdx) setJsnFiles() -- Hilfsfunktion zum Anlegen eines Sensors (reduziert Wiederholung) local function addSensor(sensorDef) iIdx = iIdx + 1 local s = {} s.idx = iIdx s.id = sensorDef.id or iTransmitterSensorID s.label = sensorDef.label s.param = sensorDef.param or 1 s.decimals = sensorDef.decimals or 0 s.type = sensorDef.sType or 4 s.unit = sensorDef.unit or "" s.valid = (sensorDef.valid ~= nil) and sensorDef.valid or true s.sensorName = sensorDef.sensorName or trans.TxSensor s.value = sensorDef.value or 0 -- Zusätzliche Felder übernehmen if sensorDef.extra then for ek, ev in pairs(sensorDef.extra) do s[ek] = ev end end variables.Sensors[iIdx] = s return iIdx end -- Sendersensor (Header, param=0) addSensor({label = trans.TxSensor, param = 0, valid = nil}) variables.TxSensIdx = iIdx -- Flüge variables.FightsIdx = addSensor({ label = trans.TxSensor_Flights, param = 2, sType = 10, unit = trans.TxSensor_FlightsUnit, extra = {valTotal = variables.Collect.flightsTotal, valToday = variables.Collect.flightsToday}, }) -- Countdown variables.CountdownTimeIdx = addSensor({ label = trans.TxSensor_CountDown, sType = 11, unit = "m:s", extra = {valSec = 0, valMin = 0, valHour = 0, valTxColor = nil}, }) -- Flugzeit variables.FlightTimeIdx = addSensor({ label = trans.TxSensor_FlightTime, sType = 5, unit = "h:m:s", extra = {valSec = 0, valMin = 0, valHour = 0}, }) -- Motorzeit variables.MotorTimeIdx = addSensor({ label = trans.TxSensor_EngineTime, sType = 5, unit = "m:s", extra = {valSec = 0, valMin = 0, valHour = 0}, }) -- TimerBeep variables.TimerBeepIdx = addSensor({ label = trans.TxSensor_TimerBeep, sType = 13, unit = "m:s", extra = {valSec = 0, valMin = 0, valHour = 0, valSign = false, valTxColor = nil, valBgColor = nil}, }) -- Command Datei laden if (variables.BeepCmd.File ~= "...") then local file = io.readall(folder..variables.BeepCmd.File..extensionJsonFile) variables.Sensors[variables.TimerBeepIdx].TimerBeepCmd = json.decode(file) end timeVars.bTime = nil -- Uhrzeit mit Datum local dt = system.getDateTime() variables.ClockIdx = addSensor({ label = string_format("%s %02d.%02d.%d", trans.TxSensor_Clock, dt.day, dt.mon, dt.year), sType = 5, extra = {valSec = dt.sec, valMin = dt.min, valHour = dt.hour}, }) -- Virtueller Sensor variables.TxVirtualSensor = addSensor({ label = trans.TxSensor_MathHeadline, value = 0.0, decimals = variables.ViS.iNachkommaA, unit = variables.ViS.unit, }) -- Sender Spannung variables.TxVoltage = addSensor({label = trans.TxSensor_TxVoltage, unit = "V"}) -- Sender Batterie Prozent variables.TxPercent = addSensor({label = trans.TxSensor_TxBattPercent, unit = "%"}) -- Sender Batterie Strom variables.TxCurrent = addSensor({label = trans.TxSensor_TxCurrent, unit = "mA"}) -- Sender Batterie Kapazität variables.TxCapacity = addSensor({label = trans.TxSensor_TxCapacity, unit = "mAh"}) -- Calca App V5.0 variables.Calca50Idx = 0 variables.GasIdx = 0 variables.SelectedIdx = 0 variables.CapacityIdx = 0 variables.FuelIdx = 0 if( (Calca_dispGas ~= nil) or (Calca_selTank ~= nil) or (Calca_capacity ~= nil) or (Calca_dispFuel ~= nil) ) then iTransmitterSensorID = 31123150 -- Calca 5.0 <--> 31123150 C(3)a(1)l(12)c(3)a(1)50 variables.Calca50Idx = addSensor({ id = iTransmitterSensorID, label = "Calca App V5.0", param = 0, valid = nil, }) local calca50Name = variables.Sensors[variables.Calca50Idx].label local calca50Sensors = { {cond = Calca_dispGas, varName = "GasIdx", label = "Gas", unit = "%"}, {cond = Calca_selTank, varName = "SelectedIdx", label = "selected Tank", unit = ""}, {cond = Calca_capacity, varName = "CapacityIdx", label = "Capacity", unit = "mAh"}, {cond = Calca_dispFuel, varName = "FuelIdx", label = "Fuel", unit = "ml"}, } for _, def in ipairs(calca50Sensors) do if def.cond ~= nil then variables[def.varName] = addSensor({ id = iTransmitterSensorID, label = def.label, unit = def.unit, sensorName = calca50Name, }) end end end -- Calca Elec App V7.x variables.Calca70Idx = 0 variables.Capacity70Idx = 0 variables.remCapaIdx = 0 variables.consCapaIdx = 0 variables.AlarmIdx = 0 variables.preAlarmIdx = 0 variables.actualCurrentIdx = 0 if(SpecTiles.calcaElec ~= nil) then iTransmitterSensorID = 31123170 -- Calca 7.0 <--> 31123170 C(3)a(1)l(12)c(3)a(1)70 variables.Calca70Idx = addSensor({ --id = iTransmitterSensorID, label = "Calca App V 6.0/7.0", param = 0, valid = nil, id = iTransmitterSensorID, label = SpecTiles.calcaElec.metadata.programName.." "..SpecTiles.calcaElec.metadata.version, param = 0, valid = nil, }) local calca70Name = variables.Sensors[variables.Calca70Idx].label local cd = SpecTiles.calcaElec local calca70Sensors = { {cond = cd.batteryCapacity, varName = "Capacity70Idx", label = "Capacity", unit = "mAh", dec = 0, val = 0}, {cond = cd.remainingPercent, varName = "remCapaIdx", label = "remaining Capacity", unit = "%", dec = 0, val = 0}, {cond = cd.consumedCapacity, varName = "consCapaIdx", label = "consumed Capacity", unit = "mAh", dec = 0, val = 0}, {cond = cd.mainAlarmPercent, varName = "AlarmIdx", label = "Alarm", unit = "%", dec = 0, val = 0}, {cond = cd.preAlarmPercent, varName = "preAlarmIdx", label = "PreAlarm", unit = "%", dec = 0, val = 0}, {cond = cd.actualCurrent, varName = "actualCurrentIdx", label = "actual Current", unit = "A", dec = 2, val = 0.0}, } for _, def in ipairs(calca70Sensors) do if def.cond ~= nil then variables[def.varName] = addSensor({ id = iTransmitterSensorID, label = def.label, unit = def.unit, decimals = def.dec, value = def.val, sensorName = calca70Name, }) end end end -- Calca Fuel App ab V1.6 variables.FuelIdx = 0 variables.tankCapacityIdx = 0 variables.fuelremPercentIdx = 0 variables.fuelmainAlarmPercentIdx = 0 variables.fuelPreAlarmPercentIdx = 0 variables.fuelUsedIdx = 0 variables.fuelFlowIdx = 0 if(SpecTiles.calcaFuel ~= nil) then iTransmitterSensorID = 31123116 -- Calca 1.6 <--> 31123170 C(3)a(1)l(12)c(3)a(1)16 aktuelle Version der calcaFuel v1.6 variables.FuelIdx = addSensor({ --id = iTransmitterSensorID, label = "Calca App V 6.0/7.0", param = 0, valid = nil, id = iTransmitterSensorID, label = SpecTiles.calcaFuel.metadata.programName.." "..SpecTiles.calcaFuel.metadata.version, param = 0, valid = nil, }) local calcaFuelName = variables.Sensors[variables.FuelIdx].label local cf = SpecTiles.calcaFuel local calcaFuelSensors = { {cond = cf.tankCapacity, varName = "tankCapacityIdx", label = "Tank Capacity", unit = "ml", dec = 0, val = 0}, {cond = cf.remainingPercent, varName = "fuelremPercentIdx", label = "remaining Percent", unit = "%", dec = 0, val = 0}, {cond = cf.mainAlarmPercent, varName = "fuelmainAlarmPercentIdx",label = "MainAlarm Percent", unit = "%", dec = 0, val = 0}, {cond = cf.preAlarmPercent, varName = "fuelPreAlarmPercentIdx", label = "PreAlarm Percent", unit = "ml", dec = 0, val = 0}, {cond = cf.fuelUsed, varName = "fuelUsedIdx", label = "Fuel used", unit = "ml", dec = 0, val = 0}, {cond = cf.fuelFlow, varName = "fuelFlowIdx", label = "Fuel flow", unit = "ml/min",dec = 0, val = 0}, } for _, def in ipairs(calcaFuelSensors) do if def.cond ~= nil then variables[def.varName] = addSensor({ id = iTransmitterSensorID, label = def.label, unit = def.unit, decimals = def.dec, value = def.val, sensorName = calcaFuelName, }) end end end -- Calca Plus App ab V5.8 variables.calcaPlusIdx = 0 variables.plusCapacityIdx = 0 variables.plusCapacity1Idx = 0 variables.plusCapacity2Idx = 0 variables.plusCRate1Idx = 0 variables.plusCRate2Idx = 0 variables.plusCRateDynIdx = 0 variables.plusremPercentIdx = 0 variables.plusconCapacityIdx = 0 variables.plusActualCurrentIdx = 0 variables.plusUSmoothIdx = 0 variables.plusBatteryTempCoreIdx = 0 variables.plusPreAlarmPercentIdx = 0 variables.plusMainAlarmPercentIdx = 0 if(SpecTiles.calcaPlus ~= nil) then iTransmitterSensorID = 31123158 -- Calca 5.8 <--> 31123170 C(3)a(1)l(12)c(3)a(1)58 ab Version der calcaPlus v5.8 variables.calcaPlusIdx = addSensor({ id = iTransmitterSensorID, label = SpecTiles.calcaPlus.metadata.programName.." "..SpecTiles.calcaPlus.metadata.version, param = 0, valid = nil, }) local calcaPlusName = variables.Sensors[variables.calcaPlusIdx].label local cp = SpecTiles.calcaPlus local calcaPlusSensors = { {cond = cp.batteryCapacity, varName = "plusCapacityIdx", label = "Capacity", unit = "mAh", dec = 0, val = 0}, {cond = cp.batteryCapacity1, varName = "plusCapacity1Idx", label = "Capacity1", unit = "mAh", dec = 0, val = 0}, {cond = cp.batteryCapacity2, varName = "plusCapacity2Idx", label = "Capacity2", unit = "mAh", dec = 0, val = 0}, {cond = cp.batteryCRate1, varName = "plusCRate1Idx", label = "CRate1", unit = "C", dec = 0, val = 0}, {cond = cp.batteryCRate2, varName = "plusCRate2Idx", label = "CRate2", unit = "C", dec = 0, val = 0}, {cond = cp.batteryCRateDyn, varName = "plusCRateDynIdx", label = "CRate dynamic", unit = "C", dec = 0, val = 0}, {cond = cp.remainingPercent, varName = "plusremPercentIdx", label = "remaining Percent",unit = "%", dec = 0, val = 0}, {cond = cp.consumedCapacity, varName = "plusconCapacityIdx", label = "consumed Capacity",unit = "mAh", dec = 0, val = 0}, {cond = cp.actualCurrent, varName = "plusActualCurrentIdx", label = "actual Current", unit = "A", dec = 1, val = 0}, {cond = cp.uSmooth, varName = "plusUSmoothIdx", label = "uSmooth", unit = "V", dec = 1, val = 0}, {cond = cp.batteryTempCore, varName = "plusBatteryTempCoreIdx", label = "Batterie core Temp.", unit = "°C", dec = 1, val = 0}, {cond = cp.preAlarmPercent, varName = "plusPreAlarmPercentIdx", label = "PreAlarm Percent", unit = "%", dec = 0, val = 0}, {cond = cp.mainAlarmPercent, varName = "plusMainAlarmPercentIdx",label = "MainAlarm Percent",unit = "%", dec = 0, val = 0}, } for _, def in ipairs(calcaPlusSensors) do if def.cond ~= nil then variables[def.varName] = addSensor({ id = iTransmitterSensorID, label = def.label, unit = def.unit, decimals = def.dec, value = def.val, sensorName = calcaPlusName, }) end end end -- Betriebsstundenzähler ab V0.61 variables.OpAccIdx = 0 variables.OpAccBZIdx = 0 variables.OpAcctotBZIdx = 0 variables.OpAcctotFZIdx = 0 variables.OpAccmodelFZIdx = 0 if(SpecTiles.OpAccHour ~= nil) then SpecTiles.OpAccHour.OpAccBZ = "0:0" SpecTiles.OpAccHour.OpAcctotBZ = "0:0" SpecTiles.OpAccHour.OpAcctotFZ = "0:0" SpecTiles.OpAccHour.OpAccmodelFZ = "0:0" iTransmitterSensorID = 1516133061 -- OpAcc v1.0 <--> 31123170 O(15)p(16)A(1)c(3)c(3)061 aktuelle Version der Betriebsdaten App v0.61 variables.OpAccIdx = addSensor({ id = iTransmitterSensorID, label = SpecTiles.OpAccHour.metadata.programName.." "..SpecTiles.OpAccHour.metadata.version, param = 0, valid = nil, }) local OpAccName = variables.Sensors[variables.OpAccIdx].label local op = SpecTiles.OpAccHour local OpAccSensors = { {cond = op.OpAccBZ, varName = "OpAccBZIdx", label = trans.TxSensor_OpTime1, unit = "h:m", dec = 0, val = 0}, {cond = op.OpAcctotBZ, varName = "OpAcctotBZIdx", label = trans.TxSensor_OpTime2, unit = "h:m", dec = 0, val = 0}, {cond = op.OpAcctotFZ, varName = "OpAcctotFZIdx", label = trans.TxSensor_OpTime3, unit = "h:m", dec = 0, val = 0}, {cond = op.OpAccmodelFZ, varName = "OpAccmodelFZIdx",label = trans.TxSensor_OpTime4, unit = "h:m", dec = 0, val = 0}, } for _, def in ipairs(OpAccSensors) do if def.cond ~= nil then variables[def.varName] = addSensor({ id = iTransmitterSensorID, label = def.label, unit = def.unit, decimals = def.dec, value = def.val, sensorName = OpAccName, sType = 12, extra = {valSec = 0, valMin = 0, valHour = 0}, }) end end end ------------------------------------------------------- -- Neue Sendersensoren in die Schnittstelle einfügen -- ------------------------------------------------------- -- Hilfsfunktion: Sensor-Werte in TelVal-Liste eintragen local function insertSensorList(sensorIdx, labelRef, sensorType, startI, endI, offsetCalc) k=k+1 j=2 TelVal.SensorListId[k] = variables.Sensors[sensorIdx].id TelVal.SensorListIdx[k] = labelRef TelVal.SensorListLabel[k] = variables.Sensors[sensorIdx].label TelVal.SensorListType[k] = sensorType for i=startI, endI do zeile = string_format("SensorListWertLabel%d", k-1) TelVal[zeile][j] = variables.Sensors[offsetCalc(i)].label zeileIdx = string_format("SensorListWertLabelIdx%d", k-1) TelVal[zeileIdx][j] = offsetCalc(i) j=j+1 end end -- Sendersensoren (Hauptsender) insertSensorList(1, 2, 2, 2, 12, function(i) return i end) -- Calca 5.0 if( (Calca_dispGas ~= nil) or (Calca_selTank ~= nil) or (Calca_capacity ~= nil) or (Calca_dispFuel ~= nil) ) then insertSensorList(variables.Calca50Idx, variables.Calca50Idx, 2, 2, 5, function(i) return variables.Calca50Idx + i end) -- Korrektur: Index-Berechnung im Original war +i-1 -- Wir korrigieren die Idx-Einträge for idx=2, j-1 do zeileIdx = string_format("SensorListWertLabelIdx%d", k-1) TelVal[zeileIdx][idx] = TelVal[zeileIdx][idx] - 1 end end -- Calca Elec 7.x if(SpecTiles.calcaElec ~= nil) then k=k+1 j=2 TelVal.SensorListId[k] = variables.Sensors[variables.Calca70Idx].id TelVal.SensorListIdx[k] = 2 TelVal.SensorListLabel[k] = variables.Sensors[variables.Calca70Idx].label TelVal.SensorListType[k] = 2 for i=2, 6 do zeile = string_format("SensorListWertLabel%d", k-1) TelVal[zeile][j] = variables.Sensors[variables.Calca70Idx + i -1].label zeileIdx = string_format("SensorListWertLabelIdx%d", k-1) TelVal[zeileIdx][j] = variables.Calca70Idx + i - 1 j=j+1 end -- Erweiterung: aktueller interpolierter Stromistwert if (SpecTiles.calcaElec.actualCurrent ~= nil) then local ci = 7 zeile = string_format("SensorListWertLabel%d", k-1) TelVal[zeile][j] = variables.Sensors[variables.Calca70Idx + ci -1].label zeileIdx = string_format("SensorListWertLabelIdx%d", k-1) TelVal[zeileIdx][j] = variables.Calca70Idx + ci - 1 j=j+1 end end -- Calca Fuel ab 1.6 if(SpecTiles.calcaFuel ~= nil) then k=k+1 j=2 TelVal.SensorListId[k] = variables.Sensors[variables.FuelIdx].id TelVal.SensorListIdx[k] = 2 TelVal.SensorListLabel[k] = variables.Sensors[variables.FuelIdx].label TelVal.SensorListType[k] = 2 for i=2, 7 do zeile = string_format("SensorListWertLabel%d", k-1) TelVal[zeile][j] = variables.Sensors[variables.FuelIdx + i -1].label zeileIdx = string_format("SensorListWertLabelIdx%d", k-1) TelVal[zeileIdx][j] = variables.FuelIdx + i - 1 j=j+1 end end -- Calca Plus ab 5.8 if(SpecTiles.calcaPlus ~= nil) then k=k+1 j=2 TelVal.SensorListId[k] = variables.Sensors[variables.calcaPlusIdx].id TelVal.SensorListIdx[k] = 2 TelVal.SensorListLabel[k] = variables.Sensors[variables.calcaPlusIdx].label TelVal.SensorListType[k] = 2 for i=2, 14 do zeile = string_format("SensorListWertLabel%d", k-1) TelVal[zeile][j] = variables.Sensors[variables.calcaPlusIdx + i -1].label zeileIdx = string_format("SensorListWertLabelIdx%d", k-1) TelVal[zeileIdx][j] = variables.calcaPlusIdx + i - 1 j=j+1 end end -- Betriebszeiten ab 0.61 if(SpecTiles.OpAccHour ~= nil) then k=k+1 j=2 TelVal.SensorListId[k] = variables.Sensors[variables.OpAccIdx].id TelVal.SensorListIdx[k] = 2 TelVal.SensorListLabel[k] = variables.Sensors[variables.OpAccIdx].label TelVal.SensorListType[k] = 2 for i=2, 5 do zeile = string_format("SensorListWertLabel%d", k-1) TelVal[zeile][j] = variables.Sensors[variables.OpAccIdx + i -1].label zeileIdx = string_format("SensorListWertLabelIdx%d", k-1) TelVal[zeileIdx][j] = variables.OpAccIdx + i - 1 j=j+1 end end ----------------------------------------------- -- Daten für die Empfängerüberwachung -- REX -- ----------------------------------------------- variables.Rex = {} -- komplettes Feld variables.Rex.Selected = {} -- Feld der eingestellten Werte variables.Rex.Selected.Index = 1 -- Default variables.Rex.Selected.sTyp = trans.menu_Rex_ModTyp1 -- Beschriftung variables.Rex.Selected.Qlimit = 80 -- Grenzwert in % variables.Rex.Selected.Qtime = 3000 -- Verzögerungszeit in ms variables.Rex.Selected.A1limit = 7 -- Wert 0 - 9 variables.Rex.Selected.A1time = 5000 -- Verzögerungszeit in ms variables.Rex.Selected.A2limit = 7 -- Wert 0 - 9 variables.Rex.Selected.A2time = 5000 -- Verzögerungszeit in ms variables.Rex.Selected.SoundQ = "" variables.Rex.Selected.SoundA1 = "" variables.Rex.Selected.SoundA2 = "" variables.Rex.Selected.SoundA1A2 = "" -- Wenn dieser Sound definiert ist, müssen zum Abspielen beide Antennen schlecht sein -- Farben für die Empfängerkacheln variables.Rex.Selected.txColorON = 43 -- Schwarz variables.Rex.Selected.txColorOFF = 44 -- Weiß variables.Rex.Selected.bgColorON = 29 -- Grün variables.Rex.Selected.bgColorOFF = 23 -- Rot variables.Rex.Selected.txColorONerror = 35 -- Blau variables.Rex.Selected.txColorOFFerror = 34 -- Hell Blau variables.Rex.Para = {} -- Parameterfeld der voreingestellten Werte variables.Rex.TypList = {} -- Liste der verschieden Modelltypen; wird später mit trans-Texten ersetzt local IDX = 0 IDX = IDX + 1 variables.Rex.Para[IDX] = {} -- 1. Datensatz variables.Rex.TypList[IDX] = trans.menu_Rex_ModelTyp1 variables.Rex.Para[IDX].Qlimit = 80 variables.Rex.Para[IDX].Qtime = 3000 variables.Rex.Para[IDX].A1limit = 7 variables.Rex.Para[IDX].A1time = 5000 variables.Rex.Para[IDX].A2limit = 7 variables.Rex.Para[IDX].A2time = 5000 IDX = IDX + 1 variables.Rex.Para[IDX] = {} variables.Rex.TypList[IDX] = trans.menu_Rex_ModelTyp2 variables.Rex.Para[IDX].Qlimit = 79 variables.Rex.Para[IDX].Qtime = 3500 variables.Rex.Para[IDX].A1limit = 6 variables.Rex.Para[IDX].A1time = 5000 variables.Rex.Para[IDX].A2limit = 6 variables.Rex.Para[IDX].A2time = 5000 IDX = IDX + 1 variables.Rex.Para[IDX] = {} variables.Rex.TypList[IDX] = trans.menu_Rex_ModelTyp3 variables.Rex.Para[IDX].Qlimit = 83 variables.Rex.Para[IDX].Qtime = 3500 variables.Rex.Para[IDX].A1limit = 7 variables.Rex.Para[IDX].A1time = 3000 variables.Rex.Para[IDX].A2limit = 7 variables.Rex.Para[IDX].A2time = 3000 IDX = IDX + 1 variables.Rex.Para[IDX] = {} variables.Rex.TypList[IDX] = trans.menu_Rex_ModelTyp4 variables.Rex.Para[IDX].Qlimit = 78 variables.Rex.Para[IDX].Qtime = 4000 variables.Rex.Para[IDX].A1limit = 7 variables.Rex.Para[IDX].A1time = 5000 variables.Rex.Para[IDX].A2limit = 7 variables.Rex.Para[IDX].A2time = 5000 IDX = IDX + 1 variables.Rex.Para[IDX] = {} variables.Rex.TypList[IDX] = trans.menu_Rex_ModelTyp5 variables.Rex.Para[IDX].Qlimit = 86 variables.Rex.Para[IDX].Qtime = 1000 variables.Rex.Para[IDX].A1limit = 8 variables.Rex.Para[IDX].A1time = 1500 variables.Rex.Para[IDX].A2limit = 8 variables.Rex.Para[IDX].A2time = 1500 IDX = IDX + 1 variables.Rex.Para[IDX] = {} variables.Rex.TypList[IDX] = trans.menu_Rex_ModelTyp6 variables.Rex.Para[IDX].Qlimit = 85 variables.Rex.Para[IDX].Qtime = 1000 variables.Rex.Para[IDX].A1limit = 7 variables.Rex.Para[IDX].A1time = 2000 variables.Rex.Para[IDX].A2limit = 7 variables.Rex.Para[IDX].A2time = 2000 IDX = IDX + 1 variables.Rex.Para[IDX] = {} variables.Rex.TypList[IDX] = trans.menu_Rex_ModelTyp7 variables.Rex.Para[IDX].Qlimit = 88 variables.Rex.Para[IDX].Qtime = 500 variables.Rex.Para[IDX].A1limit = 8 variables.Rex.Para[IDX].A1time = 1000 variables.Rex.Para[IDX].A2limit = 8 variables.Rex.Para[IDX].A2time = 1000 IDX = IDX + 1 variables.Rex.Para[IDX] = {} variables.Rex.TypList[IDX] = trans.menu_Rex_ModelTyp8 variables.Rex.Para[IDX].Qlimit = 78 variables.Rex.Para[IDX].Qtime = 2000 variables.Rex.Para[IDX].A1limit = 6 variables.Rex.Para[IDX].A1time = 3000 variables.Rex.Para[IDX].A2limit = 6 variables.Rex.Para[IDX].A2time = 3000 IDX = IDX + 1 variables.Rex.Para[IDX] = {} variables.Rex.TypList[IDX] = trans.menu_Rex_ModelTyp9 variables.Rex.Para[IDX].Qlimit = 85 variables.Rex.Para[IDX].Qtime = 500 variables.Rex.Para[IDX].A1limit = 7 variables.Rex.Para[IDX].A1time = 1000 variables.Rex.Para[IDX].A2limit = 7 variables.Rex.Para[IDX].A2time = 1000 IDX = IDX + 1 variables.Rex.Para[IDX] = {} variables.Rex.TypList[IDX] = trans.menu_Rex_ModelTyp10 variables.Rex.Para[IDX].Qlimit = 79 variables.Rex.Para[IDX].Qtime = 2000 variables.Rex.Para[IDX].A1limit = 6 variables.Rex.Para[IDX].A1time = 3000 variables.Rex.Para[IDX].A2limit = 6 variables.Rex.Para[IDX].A2time = 3000 variables.Rex.Display = {} -- Daten zur Anzeigesteuerung variables.Rex.Display.SemaphoreQ1 = false -- == false: nicht gesperrt, Ausgabe möglich; == true gesperrt Überwachung hat angesprochen variables.Rex.Display.SemaphoreA11 = false variables.Rex.Display.SemaphoreA21 = false variables.Rex.Display.SemaphoreQ2 = false variables.Rex.Display.SemaphoreA12 = false variables.Rex.Display.SemaphoreA22 = false variables.Rex.Display.SemaphoreQB = false variables.Rex.Display.SemaphoreA1B = false variables.Rex.Display.SemaphoreA2B = false se.option = 1 se.telwindows = 1 se.datens = 1 local timeMil = system.getTimeCounter() if (se.TimerZeitSpeichern) then timeVars.eLastTime = timeMil timeVars.fLastTime = timeMil timeVars.cLastTime = timeMil -- [[ -- Zeiten von ms nach s konvertieren (kompakt) for _, key in ipairs({"eTime","fTime","cTime","bTime"}) do if timeVars[key] then timeVars[key] = timeVars[key] / 1000 end end --]] end if (timeVars.eTime) then timeHMS.eMin = math_floor(timeVars.eTime/60) timeHMS.eSec = timeVars.eTime - timeHMS.eMin*60 else timeHMS.eMin, timeHMS.eSec = 0, 0 end variables.Sensors[variables.MotorTimeIdx].valSec = timeHMS.eSec variables.Sensors[variables.MotorTimeIdx].valMin = timeHMS.eMin if (timeVars.fTime) then timeHMS.fHrs = math_floor(timeVars.fTime/3600) timeHMS.fMin = math_floor(timeVars.fTime/60) % 60 timeHMS.fSec = timeVars.fTime % 60 else timeHMS.fHrs, timeHMS.fMin, timeHMS.fSec = 0, 0, 0 end variables.Sensors[variables.FlightTimeIdx].valSec = timeHMS.fSec variables.Sensors[variables.FlightTimeIdx].valMin = timeHMS.fMin variables.Sensors[variables.FlightTimeIdx].valHour = timeHMS.fHrs if (timeVars.cTime) then local abs = math_abs(timeVars.cTime) timeHMS.cMin = math_floor(abs/60) timeHMS.cSec = abs - timeHMS.cMin*60 else timeHMS.cMin, timeHMS.cSec = se.countdownMin, se.countdownSec end variables.Sensors[variables.CountdownTimeIdx].valSec = timeHMS.cSec variables.Sensors[variables.CountdownTimeIdx].valMin = timeHMS.cMin if (timeVars.bTime) then local abs = math_abs(timeVars.bTime) timeHMS.bMin = math_floor(abs/60) timeHMS.bSec = abs - timeHMS.bMin*60 else timeHMS.bMin, timeHMS.bSec = se.beepMin, se.beepSec end variables.Sensors[variables.TimerBeepIdx].valSec = timeHMS.bSec variables.Sensors[variables.TimerBeepIdx].valMin = timeHMS.bMin methods = { nil, ka.drawTelVal1, ka.drawTelVal2, ka.drawTelVal3, ka.drawTelVal4, ka.drawTelVal5, -- 2 .. 6 ka.drawTelVal6, ka.drawTelVal7, ka.drawTelVal8, ka.drawTelVal9, ka.drawTelVal10, -- 7 .. 11 ka.drawTelVal11, ka.drawTelVal12, ka.drawTelVal13, ka.drawTelVal14, ka.drawTelVal15, -- 12 .. 16 ka.drawRxMini3, -- 17 -- 33 ka.drawRxMaxi3, -- 18 -- 34 ka.drawMTAG, -- 19 -- 35 ka.drawKordinaten, -- 20 -- 36 ka.drawFlexPic1, ka.drawFlexPic2, ka.drawFlexPic3, ka.drawFlexPic4, ka.drawFlexPic5, ka.drawFlexPic6, -- 21 .. 26 ka.drawBarChart, -- 27 ka.drawRxMaxi1, -- 28 ka.drawRxMini1, -- 29 ka.drawRxMaxi2, -- 30 ka.drawRxMini2, -- 31 ka.drawTelVal16, ka.drawTelVal17, ka.drawTelVal18, ka.drawTelVal19, ka.drawTelVal20, -- 32 .. 36 ka.drawTelVal21, ka.drawTelVal22, ka.drawTelVal23, ka.drawTelVal24, -- 37 .. 40 ka.drawOszi -- 41 } UpdateHeights() sensors = {trans.empty, trans.akkuvtg} -- hier stehen die Optionen options = {trans.menu_other, trans.menu_TelVal, trans.menu_FlexPics, trans.menu_SpKa, -- 4 trans.menu_ShowSnapshot, trans.menu_motor, -- 6 trans.menu_flights, trans.menu_announce, trans.menu_sensors, trans.menu_Rex_Control, trans.menu_Oszi, trans.menu_expert} -- 12 --[[ servos = {} for i=1, 24 do servos[i] = trans.servooutput..i end --]] methodsMax = #methods sensorsMax = #sensors rx.values, values, counts, positions, params, spacers = {}, {}, {}, {}, {}, {} names, ids = {}, {} timeVars.gpsTime = 0 for i=1, rx.count do rx.values[i] = 0 end for i=1, methodsMax do counts[i] = 0 end -- Zeile for i=1, positionsMax do positions[i] = {} -- Spalten for j=1, positionMax do positions[i][j] = 1 if( counts[position] ~= nil) then counts[position] = counts[position] + 1 end end end for i=1, paramsMax do params[i] = {} for j=2, sensorsMax do params[i][j] = 0 end end spacers = nil spacers = {} for i=1, positionsMax do local sIndex = string.format("%s",i) spacers["-"..sIndex] = 2 spacers[sIndex] = 1 end setLimits() local name = "" se.nickname = pLoad("showPilotName", 0) == 1 if (not se.nickname) then name = " "..metaData.Pilot end registerForm(1, MENU_MAIN, metaData.AppName.." v"..metaData.Version, initForm, keyForm, printForm) registerTelemetry(1, metaData.AppName.." 1: "..metaData.Model..name, 4, ka.drawPage1) registerTelemetry(2, metaData.AppName.." 2: "..metaData.Model..name, 4, ka.drawPage2) timeVars.timeModel = timeMil + se.modellname * 1000 collectgarbage() end setLanguage() setColors() collectgarbage() return {init=init, loop=loop, destroy=saveSettings, author=metaData.Authors, version=metaData.Version, name=metaData.AppName}