LUA för nybörjare - Del 2.3

Post Reply
User avatar
Bamsefar
Z-Wave Kung
Posts: 1269
Joined: 25 Nov 2013, 15:06
11
Location: Stockholm

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.
Kör Home Assistant efter totalt nederlag för HomeSeer :twisted: :twisted: :mrgreen:
seven47
Medlem
Posts: 29
Joined: 02 Jan 2014, 18:47
10

Mycket bra Bamsefar! :)
SirMaggot
Medlem
Posts: 441
Joined: 18 Aug 2013, 10:36
11

Alltid intressant läsning, tackar.
seven47
Medlem
Posts: 29
Joined: 02 Jan 2014, 18:47
10

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?
Hader
Medlem
Posts: 37
Joined: 20 Aug 2014, 11:12
10

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?

Fibaro
User avatar
Bamsefar
Z-Wave Kung
Posts: 1269
Joined: 25 Nov 2013, 15:06
11
Location: Stockholm

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?
Kör Home Assistant efter totalt nederlag för HomeSeer :twisted: :twisted: :mrgreen:
Post Reply