Page 1 of 1

LUA för nybörjare - Del 2.3

Posted: 10 Dec 2014, 22:04
by Bamsefar
JSON - hur man kan hantera JSON - kort intro

Börjar med att erkänna det direkt: Jag är inte van användare av JSON i HC2an - jag har helt enkelt aldrig haft behovet så det har inte kommit mig för att titta på det således. Men nu var det ju så att någon ställde en fråga, och ja nyfiken som man är, så började jag titta lite på det hela.

Till att börja med, JSON fungerar bäst i VD (Virtuel Device), eftersom de två funktioner man vill åt enbart finns aktiva i VDs:
- json.decode - Konvertera en JSON lista till en tabell
- json.encode - Konvertera en tabell till en JSON lista

Så låt oss börja med: Vad är en JSON? eh?
Wikipedia wrote:JSON or JavaScript Object Notation, is an open standard format that uses human-readable text to transmit data objects consisting of attribute–value pairs. It is used primarily to transmit data between a server and web application, as an alternative to XML.
http://en.wikipedia.org/wiki/JSON
Aha - ett sätt att kommunicera mellan olika object i en datormiljö, och göra det i ren läsbar text och ingen superkonstig kod.

I Fibaro HC2 finns ett antal JSON rutiner som man kommer åt via API du kan läsa om dom här:
http://forum.fibaro.com/viewtopic.php?p=9344
För denna lilla guide kommer jag använda just den första:
http://<HC2 ip address>/api/rooms
Som i mitt fall, med tolv rum (nåja), ger en lista i denna stil:
[{"id":1,"name":"Sovrum","sectionID":1,"icon":"","defaultSensors":{"temperature":118,"humidity":0,"light":119},"defaultThermostat":99,"sortOrder":5},{"id":2,"name":"Arbetsrum","sectionID":1,"icon":"room_luxurychair","defaultSensors":{"temperature":52,"humidity":53,"light":54},"defaultThermostat":124,"sortOrder":6},{"id":3,"name":"Kök","sectionID":1,"icon":"room_kitchen","defaultSensors":{"temperature":0,"humidity":0,"light":0},"defaultThermostat":0,"sortOrder":3},{"id":4,"name":"Matsal","sectionID":1,"icon":"room_jadalnia","defaultSensors":{"temperature":138,"humidity":0,"light":139},"defaultThermostat":125,"sortOrder":2},{"id":5,"name":"Vardagsrum","sectionID":1,"icon":"room_cinema","defaultSensors":{"temperature":103,"humidity":0,"light":104},"defaultThermostat":0,"sortOrder":1},{"id":6,"name":"Badrum","sectionID":1,"icon":"room_laundry","defaultSensors":{"temperature":0,"humidity":0,"light":0},"defaultThermostat":0,"sortOrder":7},{"id":7,"name":"Garderob","sectionID":1,"icon":"room_polkabuty","defaultSensors":{"temperature":0,"humidity":0,"light":0},"defaultThermostat":0,"sortOrder":8},{"id":8,"name":"Hall","sectionID":1,"icon":"room_kapelusz","defaultSensors":{"temperature":0,"humidity":0,"light":0},"defaultThermostat":0,"sortOrder":4},{"id":9,"name":"Balkong","sectionID":1,"icon":"room_drzwiwejsciowe","defaultSensors":{"temperature":62,"humidity":63,"light":0},"defaultThermostat":0,"sortOrder":9},{"id":10,"name":"Scener","sectionID":2,"icon":"room_sofa","defaultSensors":{"temperature":0,"humidity":0,"light":0},"defaultThermostat":0,"sortOrder":10},{"id":11,"name":"Diverse","sectionID":3,"icon":"room_guest","defaultSensors":{"temperature":0,"humidity":0,"light":0},"defaultThermostat":0,"sortOrder":11},{"id":13,"name":"Bevakning","sectionID":2,"icon":"room_pioro","defaultSensors":{"temperature":0,"humidity":0,"light":0},"defaultThermostat":0,"sortOrder":12}]
Måste ju säga att listan inte ser sådär direkt lättläst ut - men mycket kan vi i alla fall se:
För varje rad (som är bruten på minst två rader när ni läser denna text) så finns "id", "name" osv. Och när man ser ovanstående i t.ex. en web läsare, så kan man lätt förundras över vad det är...

I vilket fall, en JSON lista kan inte rakt av hanteras inne i LUA, och till på köpet stöds vara funktionerna inne i VD's så det är inte lika lätt som tidigare att bara "kasta in koden" i en scen. Man börjar med att skapa en VD (ja jag vet, jag har inte skrivit om det - än....). Och så skapar man förslagsvis en knapp och skriver sin LUA kod i knappen.

Om vi tar exemplet ovan med api/rooms, så kommer början av koden se ut något i stil med detta:

Code: Select all

local ROOMS = Net.FHttp("192.168.1.131",80);
ROOMS:setBasicAuthentication("admin","xxx")

response ,status, errorCode = ROOMS:GET("/api/rooms");
Nej jag tänker inte gå igenom koden ovan - acceptera att den kommer att köra api'n som skapar JSON listan.

För att klara av att jobba med JSON listan, så måste vi alltså börja med att konvertera den till ett format som lättare hanterar listan, och det blir då till en vanlig tabell variabel. Förslagsvis såhär:

Code: Select all

jsonTable = json.decode(response);
Okej - så nu har vi en tabell istället och kan börja titta på det mera logiskt. T.ex. kan vi ta reda på hur många rum det finns i detta fallet:

Code: Select all

function fn_TableLength(T)
   local count = 0
   for _ in pairs(T) do count = count + 1 end
   return count
end

local NumberOfRooms = fn_TableLength(jsonTable);
Funktionen ovan känner ni igen från del 2.2 i denna guide - den räknar snabbt ut hur många rader det finns i tabellen, dvs 12 i detta exempel:

Code: Select all

fibaro:debug("Antal rum: "..NumberOfRooms);
Men om man vill titta i tabellen så måste man alltså hoppa runt mha index. Ett sätt är att som i förra delen helt enkelt skapa en loop och lista allt:

Code: Select all

for loop = 1, NumberOfRooms do
   fibaro:debug("ID: "..jsonTable[loop].id.." Namn rum "..loop..": "..jsonTable[loop].name);
end
Och det är ju trevligt.

Men om man vill åt den tredje raden i listan, så blir det alltså:

Code: Select all

fibaro:debug("ID: "..jsonTable[3].id.." Namn rum "..loop..": "..jsonTable[3].name);
Observera alltså siffran 3 istf variabeln "loop" - man måste alltså inte använda en for-loop, utan man kan direkt titta i listan.

Exakt vad man skall använda ovanstående till kan man ju undra, man kommer t.ex. åt rummets namn på andra sätt:

Code: Select all

fibaro:getRoomName(fibaro:getRoomID(i))
Men mer om det lite senare, när vi tittar lite på alarm och hur man kan nyttja det i LUA.

Re: LUA för nybörjare - Del 2.3

Posted: 11 Dec 2014, 23:21
by seven47
Mycket bra Bamsefar! :)

Re: LUA för nybörjare - Del 2.3

Posted: 12 Dec 2014, 10:20
by SirMaggot
Alltid intressant läsning, tackar.

Re: LUA för nybörjare - Del 2.3

Posted: 04 Jan 2015, 12:45
by seven47
Försöker få ut vad en property har för värde från en danalock och har använt din kod men får det inte att funka..

Använder jag REST Control appen så ser jag hela strukturen och även att propertyn ändras när jag låser/låser upp men lyckas inte få fram värdet när jag använder en VD.

Har testat att enkelt bara få fram namnen från varje rad men får det ej att funka.
Får fram att det finns 16 rows när jag gör om svaret till en json Table dock:

jsonTable = json.decode(response);

function fn_TableLength(T)
local count = 0
for _ in pairs(T) do
count = count + 1
end
return count
end

local NumberOfRows = fn_TableLength(jsonTable);
fibaro:debug(NumberOfRows);

for i = 1, NumberOfRows do
fibaro:debug(jsonTable.name)
end

Svaret:

[DEBUG] 11:44:18: 16
[ERROR] 11:44:18: line 39: attempt to index field '?' (a nil value)

Vad gör jag för fel?

Re: LUA för nybörjare - Del 2.3

Posted: 31 Jan 2015, 11:26
by Hader
seven47 wrote:Försöker få ut vad en property har för värde från en danalock och har använt din kod men får det inte att funka..

Använder jag REST Control appen så ser jag hela strukturen och även att propertyn ändras när jag låser/låser upp men lyckas inte få fram värdet när jag använder en VD.

Har testat att enkelt bara få fram namnen från varje rad men får det ej att funka.
Får fram att det finns 16 rows när jag gör om svaret till en json Table dock:

jsonTable = json.decode(response);

function fn_TableLength(T)
local count = 0
for _ in pairs(T) do
count = count + 1
end
return count
end

local NumberOfRows = fn_TableLength(jsonTable);
fibaro:debug(NumberOfRows);

for i = 1, NumberOfRows do
fibaro:debug(jsonTable.name)
end

Svaret:

[DEBUG] 11:44:18: 16
[ERROR] 11:44:18: line 39: attempt to index field '?' (a nil value)

Vad gör jag för fel?

Hej! hur går det med danalock fick du den att fungera med fibaro?

Re: LUA för nybörjare - Del 2.3

Posted: 01 Feb 2015, 18:09
by Bamsefar
Jag vet inget om danalock, men om man får index problem, så kom ihåg att:

Code: Select all

fibaro:debug(jsonTable[i].name)
Kräver att det finns ett fält som heter just "name" - och det kanske inte finns i alla JSON strukturer/tabeller?