Uppdaterad med lite bättre syntaxbeskrivning...
Jag hade ursprungligen tänkt att detta skulle ha varit i Del 2 - men tiden sprang iväg och jag bestämde mig för att dela upp variabler i två delar. Så nu kommer vi till variabler i form av listor
En lista med värden, ibland kallas det för vektor eller array i andra programmeringsspråk, kan ibland vara lämplig. Man kan t.ex. tänka sig att man definierar en lista med DeviceIDs som man vill kanske tända eller släcka, och för att slippa koda varje sådan rad så skapar man en lista och sedan "loopar" (bearbetar) man igenom denna lista. Koden blir lite mindre och smidigare - enklare att se vad man gör helt enkelt. Samma sak om man vill, som efterfrågades nyligen, slumpa fram ordningen. Och det var när jag skrev i den tråden som jag insåg att detta borde man nog ta med trots allt.
Listor kan mycket snabbt bli väldigt komplexa saker, med index och "linked lists" - men jag kommer inte gå igenom det - det är helt klart överkurs, och inte direkt något som man behöver sådär jätteofta i hemautomatiseringsbranschen
Låt oss börja med hur man definierar en lista (och i alla exempel nedan kommer jag använda samma grundtanke, en lista med DeviceIDs som man vill bearbeta):
Code: Select all
local DeviceList = { 7, 9, 13, 17 }
Code: Select all
<variabelnamn> = { värde1, värdeN }
Code: Select all
local DeviceList = { 7, 9, 13, 17 }
fibaro:debug(Device nummer 3 har ID: "..DeviceList[4])
Code: Select all
<variabelnamn>[<vilket element som motsvarar värdets plats i listan>]
Således så har vi nu alltså skapat en LOKAL list variabel, för det går (såvitt jag vet) bara att skapa lokala listor som variabler.
Om man vill se vad som finns i listan så skriver man lämpligen:
Code: Select all
for loop,Device in pairs(DeviceList) do
fibaro:debug("Index: "..loop.." DeviceID: "..Device)
end
Först och främst, och detta gäller inte bara vid listor utan så fort man vill göra något x antal gånger, så måste man på något sätt "loopa" igenom bearbetningsmängden. Det sker lämpligen med en "for" sats, och för att förenkla det hela så kan vi titta på denna kodsnutt:
Code: Select all
for loop = 1, 10 do
fibaro:debug("Loop: "..loop)
end
Dvs vi köra samma kod 10 gånger - enkel loop. Observera syntaxen, alltså hur det är skrivet:[DEBUG] 19:03:41: Loop: 1
[DEBUG] 19:03:41: Loop: 2
[DEBUG] 19:03:41: Loop: 3
[DEBUG] 19:03:41: Loop: 4
[DEBUG] 19:03:41: Loop: 5
[DEBUG] 19:03:41: Loop: 6
[DEBUG] 19:03:41: Loop: 7
[DEBUG] 19:03:41: Loop: 8
[DEBUG] 19:03:41: Loop: 9
[DEBUG] 19:03:41: Loop: 10
Code: Select all
for loop = startvärde, slutvärde do
<gör någonting>
end
Code: Select all
for loop = startvärde, slutvärde, uppräkningsvärde do
<gör någonting>
end
Code: Select all
for loop = 1, 10, 2 do
fibaro:debug("Loop: "..loop)
end
Som ni ser så har vi nu enbart ojämna värden. Och det har att göra med att man startar på värdet 1 (som är det man angivet som startvärde, och till skillnad från t.ex. programspråket C som alltid startar på noll, så rekommenderar jag att ni startar på värdet 1 - det är mera "integrerat" i LUA om man senare får för sig att vara mera extrem i sin programmering ). Sedan för varje varv så räknas värdet upp med 2, eftersom det är det vi angivet. Och vi fortsätter alltså räknar upp så länge som värdet på loop är mindre än eller lika med slutvärdet. Alltså får vi nummerserien 1,3,5,7,9 - 11 som skulle bli nästa värde är mer än 10 och alltså avbryts beräkningen.[DEBUG] 19:05:40: Loop: 1
[DEBUG] 19:05:40: Loop: 3
[DEBUG] 19:05:40: Loop: 5
[DEBUG] 19:05:40: Loop: 7
[DEBUG] 19:05:40: Loop: 9
Men om ni efter "loopen" försöker använda värdet av variabeln som ni använt för att veta vilket "varv" ni är i loopen, så kommer den variabel inte finnas kvar - den finns BARA under själva "for" bearbetningen!!! således ger följande kodsnutt:
Code: Select all
for loop = 1, 10, 2 do
fibaro:debug("Loop: "..loop)
end
fibaro:debug("Loop: "..loop)
Variabel "loop" finns inte längre efter "end" kodordet. Bara så ni vet att ni inte rakt av kan utnyttja värdet[ERROR] 19:10:57: line 39: attempt to concatenate global 'loop' (a nil value)
Det finns flera sätt att "loopa" runt, man kan t.ex. använda en s.k. "while"-loop. Den bygger på lite annan metodik. Den "loopar" tills dess att villkoret man specificerat uppfylles. Ett "klassiskt" villkor är att "loopa" för evigt, och det antagligen mest använda:
Code: Select all
while true do
<gör någonting>
end
Code: Select all
LExecuteSecond = 60 -- Execute Every N-th second
while true do
<gör någonting>
--Sleep LExecuteSecond seconds
fibaro:sleep(LExecuteSecond*1000)
end
Code: Select all
local loop=1
while loop < 10 do
fibaro:debug("Loop: "..loop)
loop=loop+1
end
Oberoende av om ni använder "for" eller "while" så ser ni förhoppningsvis att det finns ett "do" på slutet av raden, och det ordet beskriver vad du avser göra (what will you DO). Och det man syftar på är att det som står mellan "do" och "end" är det som utföres:
Code: Select all
do
<gör något då>
end
Om vi nu återgår till där jag försökte börja:
Code: Select all
local DeviceList = { 7, 9, 13, 17 }
for loop,Device in pairs(DeviceList) do
fibaro:debug("Index: "..loop.." DeviceID: "..Device)
end
Code: Select all
local loop=1
while loop < 5 do
fibaro:debug("Index: "..loop.." DeviceID: "..DeviceList[loop])
loop=loop+1
end
Code: Select all
for loop = 1, 4 do
fibaro:debug("Index: "..loop.." DeviceID: "..DeviceList[loop])
end
Code: Select all
for loop,Device in pairs(DeviceList) do
Det finns flera varianter och den funktion vi nyttjar med "pairs()" är delvis förknippad med index listor (och det tänker jag inte gå in på). Så vi nöjer oss med att ja detta fungerar för oss
Så vad kan man då göra med listan ovan. Ja om man tänker på frågan om man kan tända flera lampor men i slumpad ordning - för om man hårdkodar tändordningen så kan man inte direkt säga att det är slumpen som styr i vilken ordning som lamporna tänds eller hur? Dessvärre finns ingen superb metod att skapa en slumpad lista, så vi får ta vår lista och skapa en egen form av slumphantering:
Code: Select all
local DeviceList = { 7, 9, 13, 17 }
function fn_TableLength(T)
local count = 0
for _ in pairs(T) do count = count + 1 end
return count
end
local NumberOfDevices = fn_TableLength(DeviceList)
for loop,Device in pairs(DeviceList) do
IndexOne = math.random(1,NumberOfDevices)
IndexTwo = math.random(1,NumberOfDevices)
Temp = DeviceList[IndexOne]
DeviceList[IndexOne] = DeviceList[IndexTwo]
DeviceList[IndexTwo] = Temp
end
for loop,Device in pairs(DeviceList) do
fibaro:debug("Index: "..loop.." DeviceID: "..Device)
end
Code: Select all
local NumberOfDevices = fn_TableLength(DeviceList)
Efter att jag tagit reda på antalet element, så försöker jag med slumptalens hjälp byta plats på två åt gången, i "antal element" varv. Dvs 4 gånger kommer "for"-loopen byta två värden i listan, och nu har vi fått en lista som inte längre är i samma ordning som när vi definierade den överst i koden. T.ex. så kan det se ut såhär:
Inte direkt samma fina ordning, men skall man tända eller släcka lampor, så är det kanske en bra variant att "förvirra" tjuven.[DEBUG] 19:10:57: Index: 1 DeviceID: 13
[DEBUG] 19:10:57: Index: 2 DeviceID: 9
[DEBUG] 19:10:57: Index: 3 DeviceID: 7
[DEBUG] 19:10:57: Index: 4 DeviceID: 17