[{"content":"To jest przykładowy post utworzony w Hugo - szybkim generatorze stron statycznych napisanym w Go.\nDlaczego Hugo? Hugo to świetny wybór dla prostych blogów i stron statycznych, ponieważ:\nJest bardzo szybki - buduje strony w milisekundach Wymaga tylko jednego pliku binarnego - nie ma zależności Wspiera markdown do pisania treści Ma wbudowany serwer deweloperski z live reload Generuje w pełni statyczne pliki HTML - łatwe do hostowania Jak dodać nowy post? 1 hugo new content/post/moj-nowy-post/index.md Następnie edytuj plik markdown i uruchom serwer deweloperski:\n1 hugo server -D Deployment Do wdrożenia na produkcję wystarczy:\n1 hugo Wszystkie pliki gotowe do publikacji znajdą się w katalogu public/.\nCo dalej? Możesz teraz:\nDostosować konfigurację w hugo.toml Dodać własne posty w content/post/ Skonfigurować menu i widgety Włączyć komentarze Remark42 Miłego blogowania!\n","date":"2025-01-10T12:00:00+01:00","permalink":"https://domktorymysli.pl/p/witaj-w-hugo/","title":"Witaj w Hugo!"},{"content":" Widok strony internetowej generowanej przez moduł MB-GATEWAY od Salda.\nWiększość sprzętu można zintegrować z Grentonem przez przekaźniki, część przez Modbus. Ja natomiast, chciałem pokazać jak można się zintegrować z rekuperatorem przez Gate HTTP. W przypadku sprzętów posiadających bramkę HTTP można przeprowadzić prostą inżynierię wsteczną.\nW tym przypadku, rekuperator posiada dwa wejścia Modbus i pod jedno podłączona jest bramka http od producenta - Salda. W drugie wejście można wpląć Gate Modbus i sterować rekuperatorem, ale nie o tym jest ten post.\nPosiadam \u0026ldquo;Gateway\u0026rdquo; od Saldy (link), który pozwala na sterowanie rekuperatorem za pomocą aplikacji na telefon. Dodatkowo moduł MB-GATEWAY udostępnia stronę WWW przez którą można zarządzać samym modułem HTTP jak i podstawowymi parametrami rekuperatora. Komunikacja z telefonem odbywa się za pomocą protokołu opartego o TCP/IP na porcie 502. Jako, że Gate HTTP nie pozwala na operacje na socketach, to już nie sprawdzałem jak wygląda komunikacja dla aplikacji mobilnej.\nSprawdzenie możliwości Gate od Salda Po wejściu na stronę, za pomocą inspektora można podejrzeć, co jest wysyłane.\nMożna znaleźć kilka typów wywołań np.:\n1) GET http://192.168.0.71/FUNC(4,1,1,0,45)?160909905818\nktóre zwraca:\n0;0;1;0;0;0;0;0;0;0;0;0;1;1;1;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;\n2) GET http://192.168.0.71/FUNC(4,1,3,0,111)?1609098962765\nzwraca:\n1;22;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;53;0;0;21;53;0;0;21;53;0;0;21;53;0;0;21;53;0;0;21;53;0;0;21;53;0;0;21;53;0;0;21;53;0;0;21;53;0;0;21;53;0;0;21;53;0;0;21;53;0;0;21;53;0;0;21;53;0;0;21;53;0;0;21;53;0;0;21;53;0;0;21;53;0;0;21;53;0;0;21;53;0;0;21;53;\nPo chwili można namierzyć, że request numer 5 zawiera najwięcej interesujących danych. Stworzyłem, lokalnie na komputerze plik rekuperator.lua, w którym zaczynam pisać wstępną obsługę danych z rekuperatora.\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 -- funkcja rozdzielająca string na tablicę local function split(s, delimiter) result = {}; for match in (s..delimiter):gmatch(\u0026#34;(.-)\u0026#34; .. delimiter) do table.insert(result, match); end return result; end local result = split(response, \u0026#34;;\u0026#34;) local supply_air = result[1] local exhaust_air = result[7] local extract_air = result[4] local outside_air = result[10] local water_temperature = result[13] local humidity = result[14] local supply_fan_speed = result[16] local extract_fan_speed = result[17] -- temperatury pomnożone są przez 10 print(\u0026#34;supply_air: \u0026#34; .. supply_air / 10) print(\u0026#34;exhaust_air: \u0026#34; .. exhaust_air / 10) print(\u0026#34;extract_air: \u0026#34; .. extract_air / 10) print(\u0026#34;outside_air: \u0026#34; .. outside_air / 10) print(\u0026#34;water_temperature: \u0026#34; ..water_temperature / 10); print(\u0026#34;humidity: \u0026#34; .. humidity); print(\u0026#34;supply_fan_speed: \u0026#34; .. supply_fan_speed); Problem z Gateway Saldy Niestety po pierwszych testach okazało się, że moduł Gate nie umie sobie poradzić z response, który zwraca moduł Salda. Problem polega na tym, że po wysłaniu requestu do rekuperatora event OnResponse był wywoływany po 30 sekundach, gdzie normalnie z Postmana czy cURL request trwał jakieś 60ms.\nWydaje mi się, że Gate Http nie rozpoznaje prawidłowo zakończenia zwracanego komunikatu przez Gate Saldy - HTTP 1.0, assume close after body. Po około 20-30 sekundach w Gate Http włączany jest wewnętrzny timeout nad którym nie mam kontroli.\nPROXY Zawiedziony tym, że działa to tak strasznie wolno, postanowiłem napisać proxy, które będzie pośredniczyło w komunikacji między Grentonem a Saldą. Mogłem zrobić to za pomocą Nginx, Pythona, JavaScriptu. Ale w ramach rozrywki napisałem proxy w Go. Takie proxy umieściłem na serwerze, którego używam Grafany, HA i innych mądrości.\nMoje API do rekuperatora wygląda następująco:\n192.168.0.39:18080/recuperator/getData\n1 {\u0026#34;supplyAir\u0026#34;:\u0026#34;22.3\u0026#34;,\u0026#34;exhaustAir\u0026#34;:\u0026#34;6.1\u0026#34;,\u0026#34;extractAir\u0026#34;:\u0026#34;0.0\u0026#34;,\u0026#34;outsideAir\u0026#34;:\u0026#34;0.0\u0026#34;,\u0026#34;humidity\u0026#34;:\u0026#34;33\u0026#34;,\u0026#34;supplyFanSpeed\u0026#34;:\u0026#34;30\u0026#34;,\u0026#34;extractFanSpeed\u0026#34;:\u0026#34;30\u0026#34;,\u0026#34;fanSpeed\u0026#34;:\u0026#34;1\u0026#34;,\u0026#34;temperature\u0026#34;:\u0026#34;22\u0026#34;} Tu zdecydowałem, że większość danych przygotuję po stronie proxy, dodatkowo opakowałem wynik w JSONa, żeby już nie bawić się po stronie Grentona w parsowanie i wyciąganie danych.\n192.168.0.39:18080/recuperator/setTemperature?value=22\n1 {\u0026#34;temperature\u0026#34;:\u0026#34;22.0\u0026#34;} 192.168.0.39:18080/recuperator/setFanSpeed?value=1\n1 {\u0026#34;fanSpeed\u0026#34;:\u0026#34;1\u0026#34;} Kod proxy dostępny tutaj: https://github.com/Domktorymysli/HouseProxy (to raczej POC niż produkcyjne rozwiązanie :D)\nImplementacja w OM Tym razem skrypt był dużo prostszy dzięki JSON API:\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 if (method == \u0026#39;response\u0026#39;) then local response = GATE-\u0026gt;RecuperatorRequest-\u0026gt;ResponseBody if response.humidity ~= nil then RECUPERATOR_DATA = response end if response.temperature ~= nil then RECUPERATOR_DATA[\u0026#39;temperature\u0026#39;] = response.temperature end if response.fanSpeed ~= nil then RECUPERATOR_DATA[\u0026#39;fanSpeed\u0026#39;] = response.fanSpeed end RECUPERATOR_DATA_STR = toString(RECUPERATOR_DATA) return end if (method == \u0026#39;getData\u0026#39;) then doRequest(\u0026#34;recuperator/getData\u0026#34;) return end if (method == \u0026#39;setFanSpeed\u0026#39;) then doRequest(\u0026#34;recuperator/setFanSpeed?value=\u0026#34; .. value) return end if (method == \u0026#39;setTemperature\u0026#39;) then doRequest(\u0026#34;recuperator/setTemperature?value=\u0026#34; .. value) return end Podsumowanie Z dość prostego przykładu zrobił się całkiem długi post. Prawdopodobnie, gdyby Salda i Grenton lepiej ze sobą współpracowały, to bym uniknął zabawy z pisaniem proxy. Z drugiej strony, może komuś kiedyś się przytrafi podobny błąd.\n","date":"2021-01-03T12:00:00+01:00","image":"https://domktorymysli.pl/p/rekuperator-salda-przez-gate-http/rekuperator_1_hu_c8387acfc0fe5d71.png","permalink":"https://domktorymysli.pl/p/rekuperator-salda-przez-gate-http/","title":"Rekuperator Salda przez Gate HTTP"},{"content":"\nIFTTT to platforma pozwalająca w łatwy sposób tworzyć proste aplety pozwalające na integrację usług znajdujących się w internecie. Podłączenie Grentona przez Gate Http jest dość proste, dlatego w ramach rozrywki, pokażę jak szybko można zintegrować Grentona np. z Asystentem Google.\nKonfiguracja IFTTT Oczywiście potrzebujesz konta na IFTTT. Potem należy stworzyć nowy applet.\nKlikamy w + i wybieramy \u0026ldquo;Google Assistant\u0026rdquo;, a potem \u0026ldquo;Say a phrase with a text ingredient\u0026rdquo;, bo chcemy dodać własny parametr. Trzeba wpisać na jakie komendy ma reagować:\nNiestety w IFTTT integracja z Google Asystentem działa póki co w języku angielskim, dlatego w ustawieniach asystenta musisz dodać język angielski (bez tego nie będzie działało).\nPo tym jak utworzymy \u0026ldquo;trigger\u0026rdquo;, klikamy na \u0026ldquo;+\u0026rdquo; przy that i wybieramy serwis \u0026ldquo;Webhooks\u0026rdquo;.\nI konfigurujemy w następujący sposób:\nAdres URL to będzie publiczny adres Twojego Gate Http. Na routerze powinieneś wystawić port 80 (lub inny), tak żeby moduł Gate był dostępny z internetu. Jeśli masz stałe publiczne IP, to będzie prosto. Natomiast jeśli Twoje IP się zmienia, to przyda Ci się jakiś DynDNS typu www.duckdns.org.\nNagłówek \u0026ldquo;Content Type\u0026rdquo; ustawiamy na: \u0026ldquo;text/plain\u0026rdquo;, bo chcemy żeby było prosto, a w ciele wstawiamy \u0026ldquo;ingredient\u0026rdquo; którym jest nazwa pomieszczenia w którym włączamy światło.\nSkrypt w OM Teraz w OM, dla modułu Gate należy przygotować \u0026lsquo;HttpListener\u0026rsquo;. U mnie wygląda on tak:\nW zasadzie zmieniłem tylko pole \u0026ldquo;path\u0026rdquo; na wartość \u0026ldquo;/lightOn\u0026rdquo;, stworzyłem też nowy skrypt o nazwie \u0026ldquo;IFTTT_light_on()\u0026rdquo; i dodałem go do zdarzenia \u0026ldquo;OnRequest\u0026rdquo; obiektu \u0026ldquo;IFTTT_webhook\u0026rdquo;\nCiało skryptu (funkcji) GATE-\u0026gt;IFTTT_light_on() wygląda następująco:\n1 2 3 4 5 6 7 8 9 10 11 local body = GATE-\u0026gt;IFTTT_webhook-\u0026gt;RequestBody -- przepisujemy request body do zmiennej lokalnej if (body == \u0026#34;office\u0026#34;) then -- jeżeli w ciele znajduje się słowo \u0026#34;office\u0026#34; to włącz światło DOM-\u0026gt;P1_26_R7_BIURO_SWIATLO-\u0026gt;SwitchOn(0) end if (body == \u0026#34;living room\u0026#34;) then -- jeżeli w ciele znajduje się słowo \u0026#34;living room\u0026#34; to włącz światło w salonie DOM-\u0026gt;P1_30_R7_SALON_LED-\u0026gt;Switch(0) end GATE-\u0026gt;IFTTT_webhook-\u0026gt;SendResponse() -- zakończ request i wyślij odpowiedź I to w sumie wszystko. Dalej możesz dodać kolejny listener do wyłączania świateł.\nBłędy Jeżeli coś Ci nie działa, to możesz użyć Postmana i próbować wywołać akcję na Gate lokalnie. Tak jakby to robił IFTTT:\nJak już uda Ci się wywołać akcję (nie dostaniesz błędu 5xx lub 4xx), to powoli możesz dodawać kolejne linie kodu włączające światło.\nBezpieczeństwo Dla uproszczenia pominąłem wątek bezpieczeństwa. Dlatego swój skrypt możesz zabezpieczyć dodatkowo jakimś parametrem w URL, który będzie kluczem. Nie jest to idealne rozwiązanie, ale w większości wypadków wystarczające. Na pewno nie podłączaj webhooków IFTTT pod skrypt rozbrajania alarmu czy otwierania bramy garażowej 😊\nPozdrawiam, T\n","date":"2020-08-24T12:00:00+02:00","image":"https://domktorymysli.pl/p/grenton-integracja-z-ifttt/ifThisThenThat_hu_178d7464fc89ce9a.png","permalink":"https://domktorymysli.pl/p/grenton-integracja-z-ifttt/","title":"Grenton integracja z IFTTT"},{"content":" Grenton Gate Http\nPo jakimś czasie zacząłem się interesować modułem GATE HTTP od Grentona. W ramach posta zrobiłem kilka prostych testów, które pozwoliły mi zrozumieć jak działa moduł HTTP GATE. Może komuś się przyda.\nModuł pozwala dodać dwa typy obiektów: Request – służący do wysyłania zapytań HTTP oraz Response – służący jako prosty server HTTP. W tym wpisie zajmę się obiektem Request, ponieważ za to on pozwala na proste integracje, np. z pogodą.\nPostawiłem sobie prosty serwer HTTP napisany w Pythonie i zacząłem wysyłać do niego zapytania za pomocą modułu GATE HTTP. Serwer stoi pod adresem 192.168.0.51 na porcie 8080.\nTypy requestów Przypadek 1 (request type none) GET request bez nagłówków Content-Type. Rezultat: serwer otrzymał zapytanie z parametrami queryString.\nPrzypadek 2 (request type text) Zmiana typu na text (1) dodaje nagłówek: Content-Type: text/plain\nPrzypadek 3 (request type json) Typ json (2) dodaje nagłówek: Content-Type: application/json\nPrzypadek 4 (request type xml) Typ xml (3) dodaje nagłówek: Content-Type: text/xml\nPrzypadek 5 (request form data) Typ form-data (4) dodaje nagłówek: Content-Type: application/x-www-form-urlencoded\nNiestandardowe nagłówki Można definiować własne nagłówki za pomocą tablicy:\n1 2 3 headers = {} headers[\u0026#34;Access-Token\u0026#34;] = \u0026#34;bearer 1234\u0026#34; GATE-\u0026gt;RequestObject-\u0026gt;SetRequestHeaders(headers) Nagłówki Content-Type są dodawane po nagłówkach użytkownika, bez nadpisywania.\nPOST z danymi Wysłanie POST z body: \u0026ldquo;text, text, text\u0026rdquo; i nagłówkami działa prawidłowo. Content-Length wynosi 16 bajtów.\nUwaga: GATE nie konwertuje automatycznie tablic Lua na JSON czy XML. Aby wysłać sformatowane dane, należy użyć zewnętrznych bibliotek.\nPrzykład - OpenWeatherMap API Wysyłając GET request z responseType = 2 (JSON), odpowiedź jest parsowana do tablicy Lua:\n1 2 3 4 -- Dostęp do pól odpowiedzi temp = body.main.temp pressure = body.main.pressure icon = body.weather[1].icon Podsumowanie Wydaje mi się, że przedstawiłem większość najciekawszych przypadków jak zachowuje się obiekt Request. Typy requestu głównie dodają nagłówki. Dla konwersji danych można użyć bibliotek JSON i XML:\njson.lua xml2lua Instrukcja Grentona: GATE-HTTP User Manual\n","date":"2020-03-29T12:00:00+02:00","image":"https://domktorymysli.pl/p/gate-http-request/gate_hu_f862693b5e1d89c0.jpeg","permalink":"https://domktorymysli.pl/p/gate-http-request/","title":"GATE HTTP (1/2) – request"},{"content":" Grenton Smart Panel\nFirma Grenton wysłała mi swój nowy \u0026ldquo;Grenton Smart Panel\u0026rdquo; do testów za co bardzo dziękuję. W tym poście chciałbym Wam pokazać czego się dowiedziałem w ciągu ostatnich kilku dni.\nNowy panel dotykowy Na wizualizacjach nowy panel wygląda następująco:\nGrenton Smart Panel – wizualizacja\nW rzeczywistości różni się kilkoma detalami. Po pierwsze, logo jest mniej widoczne, co jest na plus. Po drugie, koło diod umieszczone są czujniki wykrywające gesty. Na dole pod logiem znajduje się czujnik zmierzchu.\nDokładna instrukcja dostępna jest pod adresem: http://www.grenton.pl/upload/files/PL/GRENTON_SMART_PANEL_TF-Bus.pdf\nDane techniczne zasilanie: 5-24V DC średni pobór prądu w trybie czuwania (dla 5V): 20 mA maks. pobór prądu (dla 5V): 80 mA waga: 120 g zakres temperatur pracy: 0-45°C wymiary (wys/szer/głęb): 80/80/10 mm Tył panelu i podłączenie Grenton zrezygnował ze swojego złącza TF-BUS na rzecz zwykłych śrubek. Adapter ARK pozwalający na podłączenie poprzedniego panelu kosztował 39 zł i trzeba było go zamontować w puszce wraz z każdym panelem dotykowym, teraz potrzeba znacznie mniej adapterów.\nGrenton Smart Panel – tył\nZ tyłu obudowy wystaje karta SD (4GB!), prawdopodobnie to na niej trzymane są ikony. Ta część w prawym dolnym rogu to chyba głośnik. Część w lewym górnym rogu to silnik do wibracji.\nInformacje przekazywane użytkownikowi Panel dotykowy pozwala przekazać całkiem sporo informacji:\nNa wyświetlaczu oled można wyświetlić tekst, ikony, pliki bmp oraz rysować za pomocą Lua Przy każdym z przycisków można wyświetlić dwie różne ikony, zależnie od stanu przycisku Diody przy każdym z przycisków mogą świecić w dwóch kolorach – zielony i czerwony Panel może wydawać piszczący dźwięk (można go wyłączyć) Dodatkowo wszystko jest sterowane za pomocą Lua.\nRozpoznawanie gestów Przy każdej z diod sygnalizujących stan przycisku, umieszczony jest czujnik pozwalający wykryć gest. Panel rozpoznaje cztery gesty – ruchy ręką w lewo, prawo, górę i dół. Gesty tłumaczone są na zdarzenia w OM, przez co ich obsługa w Lua jest całkiem prosta.\nWyświetlacz OLED Wyświetlacz ma rozdzielczość 128 x 64 piksele. Jest dość jasny, ma dobry kontrast. Panel jest bardzo czuły - delikatny kontakt z palcem powoduje reakcję. Można nacisnąć wiele przycisków w tym samym momencie.\nWyświetlanie tekstu Przykład wyświetlenia tekstu:\n1 2 3 DOM-\u0026gt;x250000067_PANEL1-\u0026gt;ClearScreen() DOM-\u0026gt;x250000067_PANEL1-\u0026gt;PrintText(0,0,\u0026#39;ABCDEFGHIJKLMNOPRSTUWYZ\u0026#39;,1) DOM-\u0026gt;x250000067_PANEL1-\u0026gt;DisplayContent() Największym fontem (3) można wyświetlić na ekranie około 6 liter. Polskie znaki działają, ale kodowane są w utf-8, gdzie jeden znak zajmuje dwa bajty.\nRysowanie Aby móc rysować, trzeba przełączyć wyświetlacz w tryb \u0026ldquo;freedraw\u0026rdquo; metodą DisplayContent(). Żeby wrócić do trybu przycisków – metoda ShowButtons().\n1 2 3 DOM-\u0026gt;x250000067_PANEL1-\u0026gt;DrawIcon(10,10,\u0026#34;lamp2off\u0026#34;) DOM-\u0026gt;x250000067_PANEL1-\u0026gt;DrawLine(0,0,127,63,1) DOM-\u0026gt;x250000067_PANEL1-\u0026gt;DisplayContent() W trybie \u0026ldquo;freeDraw\u0026rdquo; przyciski działają tak jak zostały skonfigurowane wcześniej, można dalej włączać urządzenia podpięte pod przyciski.\nCo jest na karcie pamięci? Na karcie pamięci znajdują się pliki BMP z ikonami. Karta jest sformatowana w formacie FAT32. Wszystkie ikony mają rozmiar 64 x 32 piksele (1/4 ekranu).\nMożna dodawać własne ikony za pomocą ImageMagick:\n1 convert b04.gif -resize 128 -crop 128x64+0+25 +repage -monochrome -type Grayscale -colors 2 -negate xkot%02d.bmp Animacja Można tworzyć animacje za pomocą timera, który w określonych odstępach czasu zmienia klatki:\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 if _G[\u0026#39;x\u0026#39;] == nil then _G[\u0026#39;x\u0026#39;] = 0 _G[\u0026#39;y\u0026#39;] = 0 _G[\u0026#39;xx\u0026#39;] = 1 _G[\u0026#39;xy\u0026#39;] = 1 end _G[\u0026#39;x\u0026#39;] = _G[\u0026#39;x\u0026#39;] + _G[\u0026#39;xx\u0026#39;]; _G[\u0026#39;y\u0026#39;] = _G[\u0026#39;y\u0026#39;] + _G[\u0026#39;xy\u0026#39;]; if (_G[\u0026#39;x\u0026#39;] \u0026gt;= 64) or (_G[\u0026#39;x\u0026#39;] \u0026lt;= 0) then _G[\u0026#39;xx\u0026#39;] = _G[\u0026#39;xx\u0026#39;] * -1 end if (_G[\u0026#39;y\u0026#39;] \u0026gt;= 32) or ( _G[\u0026#39;y\u0026#39;] \u0026lt;= 0) then _G[\u0026#39;xy\u0026#39;] = _G[\u0026#39;xy\u0026#39;] * -1 end DOM-\u0026gt;x250000067_PANEL1-\u0026gt;ClearScreen() DOM-\u0026gt;x250000067_PANEL1-\u0026gt;DrawIcon(_G[\u0026#39;x\u0026#39;],_G[\u0026#39;y\u0026#39;],\u0026#34;lamp2on\u0026#34;) DOM-\u0026gt;x250000067_PANEL1-\u0026gt;DisplayContent() Sterowanie termostatem Panel można wykorzystać jako termostat pokojowy. Przykład implementacji:\nButton1/3 – sterowanie światłami (bistabilne) Button2 – przycisk \u0026ldquo;plus\u0026rdquo; (monostabilny, ikona = plus) Button4 – przycisk \u0026ldquo;minus\u0026rdquo; (monostabilny, ikona = minus) Skrypt zmieniający temperaturę:\n1 2 3 local value = DOM-\u0026gt;termostat-\u0026gt;PointValue DOM-\u0026gt;termostat-\u0026gt;SetPointValue(value + temp) DOM-\u0026gt;timer2-\u0026gt;Start() Skrypt wyświetlający temperaturę:\n1 2 3 4 5 6 7 local temp = DOM-\u0026gt;x250000067_PANELSENSTEMP1-\u0026gt;Value local pointValue = DOM-\u0026gt;termostat-\u0026gt;PointValue DOM-\u0026gt;x250000067_PANEL1-\u0026gt;ClearScreen() DOM-\u0026gt;x250000067_PANEL1-\u0026gt;PrintText(20,0,\u0026#39;Temp. pokój 1:\u0026#39;,1) DOM-\u0026gt;x250000067_PANEL1-\u0026gt;PrintFloat(45,20,temp,2,1) DOM-\u0026gt;x250000067_PANEL1-\u0026gt;PrintFloat(45,40,pointValue,2,1) DOM-\u0026gt;x250000067_PANEL1-\u0026gt;DisplayContent() Podsumowanie Plusy:\nFajny, responsywny gadżet Można przekazać użytkownikowi bardzo dużo informacji Ogromne możliwości dzięki Lua Api jest spójne z dotychczasowymi produktami Grentona Pozwala wgrywać własne ikony, tworzyć menu i wyświetlać proste animacje Minusy:\nInstrukcja mogłaby zawierać dokumentację metod wraz z parametrami Nie można wgrać obrazków na panel za pomocą OMa, trzeba wyciągać kartę z panelu Nie można pobrać listy obrazków jakie znajdują się na panelu Strasznie się palcuje Drobne bugi z fontami i niekonsekwencje w ograniczeniu pól w OM Podsumowując panel bardzo mi się podoba. Jeśli macie jakieś pytania to chętnie odpowiem.\nPozdrawiam, T\n","date":"2018-02-04T12:00:00+01:00","image":"https://domktorymysli.pl/p/grenton-smart-panel/DSC_6746_wykadrowane_hu_ff8338e454b0bfc2.jpg","permalink":"https://domktorymysli.pl/p/grenton-smart-panel/","title":"Grenton – Smart Panel"}]