Node-RED

1.Co to jest Node-RED?

Node-RED Numeron

Node-RED to środowisko programistyczne w którym za pomocą bloków możemy utworzyć algorytm programu. Node-RED oparty jest o node.js (JavaScript – język skryptowy). Projekt który został zapoczątkowany przez IBM oddany w ręce społeczności, obecnie rozwija się bardzo dynamicznie. Projekt działa na wszystkich platformach tj. Windows, MacOS oraz Linuks i pozwala w prosty sposób wkroczyć w świat Przemysłowego Internetu Rzeczy.

Nowoczesne urządzenia NUMERON proBox2, proBox2ETH i smartBOX (w odpowiedniej wersji hardware) wyposażone są standardowo w pełni funkcjonalne wersje Node-RED. Urządzenia udostępniają odczytane dane z liczników za pomocą wewnętrznej szyny danych w taki sposób, że aplikacje napisane w Node-RED mogą z nich bezpośrednio korzystać.

Poniżej znajdą Państwo instrukcję konfiguracji, uruchomienia prostego ekranu wizualizacji oraz szereg gotowych przykładów do wykorzystania.

Tak Nie Zaproponuj zmianę
Ostatnia aktualizacja 4 czerwca 2018
0 of 0 użytkowników uznało to za pomocne

2.Konfiguracja urządzeń

Aby rozpocząć korzystanie z modułu Node-RED w urządzeniach NUMERON należy wykonać kilka czynności konfiguracyjnych.

Po pierwsze należy upewnić się, że moduł jest włączony i/lub włączyć go wchodząc do menu “Node-RED – konfiguracja”,

i przestawić opcję menu na “włączony”.

Tak Nie Zaproponuj zmianę
Ostatnia aktualizacja 23 lipca 2018
1 of 1 użytkowników uznało to za pomocne

2.1.Konfiguracja odczytów

Aby aplikacje Node-RED mogły wizualizować dane pozyskiwane przez urządzenie (proBox2, proBox2ETH, smartBOX) na którym są uruchomione należy odpowiednio skonfigurować to urządzenie. Zachęcamy do wcześniejszego zapoznania się z DTR konkretnego urządzenia. Zawarte są tam niezbędne informacje dotyczące fizycznego podłączenia liczników do interfejsów urządzenia, jak również konfiguracji harmonogramów odczytowych.

Poniżej skrót najważniejszych ustawień niezbędnych do pozyskania danych w aplikacjach Node-RED.

Po wprowadzeniu/przy wprowadzaniu licznika na listę urządzeń w urządzeniu (menu “Odczyt urządzeń -> Lista urządzeń”), pozycję “Przetwarzanie danych online” należy ustawić na “Tak”.

Następnie proszę upewnić się, że dany licznik znajduje się na liście harmonogramu Online.

Tak Nie Zaproponuj zmianę
Ostatnia aktualizacja 4 czerwca 2018
0 of 0 użytkowników uznało to za pomocne

2.2.Logowanie do Node-RED

Aby przejść do ekranu administracyjnego należy z menu urządzenia wybrać “Node-RED – schemat”.

Wyświetli się ekran logowania.

Nazwa użytkownika (Username) to: admin

Hasło (Password) to bieżące hasło administracyjne do urządzenia. Hasło do ekranu administracyjnego Node-RED będzie automatycznie zmieniać się wraz ze zmianą głównego hasła.

Tak Nie Zaproponuj zmianę
Ostatnia aktualizacja 23 lipca 2018
0 of 0 użytkowników uznało to za pomocne

3.Ekran administracyjny

Po zalogowaniu do ekranu administracyjnego Node-RED powinien pojawić się ekran z domyślnymi schematami aplikacji.

Pierwsza zakładka “Flow 1” jest gotowa na projektowanie własnej aplikacji. W wyłączonej (wyszarzonej) zakładce “Demo (dane z liczników)” znajduje się przykład wizualizacji dla jednego licznika. W następnym kroku pokazano jak z niego skorzystać.

Tak Nie Zaproponuj zmianę
Ostatnia aktualizacja 5 czerwca 2018
0 of 0 użytkowników uznało to za pomocne

3.1.Użycie domyślnego przykładu

Aby skorzystać z wgranego domyślnie przykładu wizualizacji należy go w pierwszej kolejności włączyć.

Dwukrotne kliknięcie w nazwę zakładki otwiera menu podręczne, gdzie możemy m.in. zmienić jej nazwę, ale przede wszystkim ją włączać i wyłączać.

Zmieniamy kliknięciem status zakładki (grafu – aplikacji) na “Enabled” i zamykamy okno właściwości przyciskiem “Done”.

Następnie należy zmienić przykładowy numer licznika, na numer fizycznego licznika podłączonego do urządzenia, który został skonfigurowany wcześniej w rozdziale “Konfiguracja odczytów”.

Klikamy dwukrotnie na element grafu “Licznik 96481317” i zmieniamy numer licznika z 96481317 na numer swojego licznika odczytywanego przez urządzenie.

Zamykamy okno właściwości przyciskiem “Done”, a na sam koniec zapisujemy wszystkie grafy i zakładki za pomocą przycisku “Deploy” w prawym górnym rogu.

Po zapisaniu zmian, ekran wizualizacji “Dashboard” możemy wyświetlić klikając znaczek  w zakładce, w prawym górnym rogu albo wybierając opcję “Node-RED – dashboard” w menu urządzenia.

Tak Nie Zaproponuj zmianę
Ostatnia aktualizacja 23 lipca 2018
0 of 0 użytkowników uznało to za pomocne

4.Import gotowego szablonu

Importowanie gotowych szablonów do swojego środowiska Node-RED polega na skopiowaniu i wklejeniu przygotowanego kodu.

Proszę przejść do pozycji z szablonem, a następnie skopiować (do schowka) kod np. za pomocą przycisku “copy”  lub pobrać plik, otworzyć go w “notatniku”, i dopiero skopiować.

Następnie przechodzimy do okna administracyjnego Node-RED, i z menu w prawym górnym rogu ekranu wybieramy opcję “Import -> Clipboard”.

 

Wklejamy (CTRL+V) zawartość schowka w nowo otwartym oknie i klikamy w przycisk “Import”.

W wyniku otrzymamy nową zakładkę z zaimportowanym kodem wybranego szablonu.

Kolejnym krokiem będzie zapis “Deploy” lub wcześniejsza modyfikacja grafu np. zmiana numeru licznika.

Oto efekt importu domyślnego szablonu i zmiany numeru licznika.

Tak Nie Zaproponuj zmianę
Ostatnia aktualizacja 5 czerwca 2018
0 of 0 użytkowników uznało to za pomocne

5.Import modułów do urządzeń

W celu aktualizacji niektórych funkcji lub dodaniu nowych należy wgrać odpowiednie moduły do urządzeń.

Wybieramy menu “Moduły -> Dodanie modułu/licencji”,

wskazujemy właściwy plik, i klikamy przycisk “Dodaj”.

Tak Nie Zaproponuj zmianę
Ostatnia aktualizacja 23 lipca 2018
0 of 0 użytkowników uznało to za pomocne

5.1.Moduł Plotly.js

Moduł Plotly.js dodaje bibliotekę graficzną do zasobów urządzenia Numeron, aby móc z niej skorzystać bez dostępu do Internetu. Zamiast kodu:

<script src="https://node-red.numeron.pl/plotly-1.34.0.min.js"></script>

można użyć:

<script src="/static/plotly-1.34.0.min.js"></script>

Pierwsza wersja modułu uwzględnia bibliotekę w wersji 1.34.0. Jeśli zajdzie potrzeba użycia biblioteki w innej wersji zostanie taka wersja udostępniona.

Moduł funkcyjny Plotly.js v1.34.0
Tak Nie Zaproponuj zmianę
Ostatnia aktualizacja 9 listopada 2018
0 of 0 użytkowników uznało to za pomocne

6.Gotowe szablony grafów/aplikacji

Poniżej zamieszczamy przykładowe szablony grafów/aplikacji do wykorzystania w Państwa wdrożeniach. Zachęcamy do modyfikacji i rozwijania istniejących przykładów.

Służymy również pomocą w przygotowaniu, opracowaniu i wdrożeniu dedykowanych wizualizacji według Państwa pomysłu i projektu. Wymaga to dodatkowych ustaleń i wyceny. Zapraszamy do rozmowy -> Kontakt

Część z poniższych przykładów mogą Państwo obejrzeć na żywo na serwerze demo pod adresem https://node-red.numeron.pl/ui/

Tak Nie Zaproponuj zmianę
Ostatnia aktualizacja 4 czerwca 2018
0 of 0 użytkowników uznało to za pomocne

6.1.Domyślny schemat startowy Demo

Pobierz plik  Domyślny schemat startowy Demo lub skopiuj poniższy kod:

[
    {
        "id": "dd9c4191.af407",
        "type": "tab",
        "label": "Demo [Dane z liczników]",
        "disabled": false,
        "info": ""
    },
    {
        "id": "c505834.b962b8",
        "type": "json",
        "z": "dd9c4191.af407",
        "name": "json",
        "x": 210,
        "y": 60,
        "wires": [
            [
                "ecdd5ab0.c755f8",
                "505114e0.49b1ac"
            ]
        ]
    },
    {
        "id": "ecdd5ab0.c755f8",
        "type": "switch",
        "z": "dd9c4191.af407",
        "name": "Licznik 96481317",
        "property": "payload.data[0].number",
        "propertyType": "msg",
        "rules": [
            {
                "t": "eq",
                "v": "96481317",
                "vt": "str"
            }
        ],
        "checkall": "true",
        "outputs": 1,
        "x": 130,
        "y": 320,
        "wires": [
            [
                "81dd5338.ce71d",
                "410e74e3.f42a9c",
                "b662a363.0a4f6",
                "12a97e65.e56552",
                "88e14f47.0216b"
            ]
        ]
    },
    {
        "id": "81dd5338.ce71d",
        "type": "Input Split",
        "z": "dd9c4191.af407",
        "name": "Moce P+",
        "inputProps": [
            "payload.data[0].data.energy.PP",
            "payload.data[0].data.energy.PP_L1",
            "payload.data[0].data.energy.PP_L2",
            "payload.data[0].data.energy.PP_L3"
        ],
        "inputTopics": [
            "P+Sum",
            "P+ L1",
            "P+ L2",
            "P+ L3"
        ],
        "outputs": 4,
        "x": 420,
        "y": 80,
        "wires": [
            [
                "1e003d2e.bd1863",
                "dc3c131a.10967"
            ],
            [
                "1e003d2e.bd1863"
            ],
            [
                "1e003d2e.bd1863"
            ],
            [
                "1e003d2e.bd1863"
            ]
        ]
    },
    {
        "id": "57d92c7f.76db94",
        "type": "udp in",
        "z": "dd9c4191.af407",
        "name": "proBox",
        "iface": "",
        "port": "1910",
        "ipv": "udp4",
        "multicast": "false",
        "group": "",
        "datatype": "utf8",
        "x": 70,
        "y": 60,
        "wires": [
            [
                "c505834.b962b8"
            ]
        ]
    },
    {
        "id": "410e74e3.f42a9c",
        "type": "Input Split",
        "z": "dd9c4191.af407",
        "name": "Prognoza",
        "inputProps": [
            "payload.data[0].data.energy.PredictedPower",
            "payload.data[0].data.energy.GrowingPower"
        ],
        "inputTopics": [
            "PredictedPower",
            "GrowingPower"
        ],
        "outputs": 2,
        "x": 420,
        "y": 180,
        "wires": [
            [
                "d0721be6.971fd8"
            ],
            []
        ]
    },
    {
        "id": "b662a363.0a4f6",
        "type": "Input Split",
        "z": "dd9c4191.af407",
        "name": "Napięcia",
        "inputProps": [
            "payload.data[0].data.energy.U_L1",
            "payload.data[0].data.energy.U_L2",
            "payload.data[0].data.energy.U_L3"
        ],
        "inputTopics": [
            "U_L1",
            "U_L2",
            "U_L3"
        ],
        "outputs": 3,
        "x": 420,
        "y": 300,
        "wires": [
            [
                "7152669d.676e18"
            ],
            [
                "8f9f45ba.13b448"
            ],
            [
                "73c944a2.cf58ec"
            ]
        ]
    },
    {
        "id": "1f672acd.848e05",
        "type": "ui_audio",
        "z": "dd9c4191.af407",
        "name": "",
        "group": "f464e111.78b9",
        "voice": "0",
        "always": true,
        "x": 820,
        "y": 400,
        "wires": []
    },
    {
        "id": "88e14f47.0216b",
        "type": "function",
        "z": "dd9c4191.af407",
        "name": "Alarm U",
        "func": "\nvar str;\nvar U = new Array(3);\nvar maxU = 280;\n\nU[0] = msg.payload.data[0].data.energy.U_L1;\nU[1] = msg.payload.data[0].data.energy.U_L2;\nU[2] = msg.payload.data[0].data.energy.U_L3;\n\nstr = \"U1=\" + U[0] + \", U2=\" + U[1] + \", U3=\" + U[2];\nif ((U[0] > maxU) || (U[1] > maxU) || (U[2] > maxU)) \n{\n    str = \"Alarm, napięcie \" + str;\n    var newMsg = { payload: str };\n    \n    return newMsg\n}\n\nreturn null;",
        "outputs": 1,
        "noerr": 0,
        "x": 420,
        "y": 400,
        "wires": [
            [
                "1b63d8ae.8e9ef7"
            ]
        ]
    },
    {
        "id": "1b63d8ae.8e9ef7",
        "type": "delay",
        "z": "dd9c4191.af407",
        "name": "",
        "pauseType": "rate",
        "timeout": "5",
        "timeoutUnits": "seconds",
        "rate": "1",
        "nbRateUnits": "15",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "x": 620,
        "y": 400,
        "wires": [
            [
                "d6a9f6ca.36d5b8",
                "1f672acd.848e05"
            ]
        ]
    },
    {
        "id": "1e003d2e.bd1863",
        "type": "ui_chart",
        "z": "dd9c4191.af407",
        "name": "",
        "group": "f464e111.78b9",
        "order": 2,
        "width": "14",
        "height": "6",
        "label": "Wykres P [W]",
        "chartType": "line",
        "legend": "true",
        "xformat": "HH:mm:ss",
        "interpolate": "bezier",
        "nodata": "",
        "ymin": "",
        "ymax": "",
        "removeOlder": "1",
        "removeOlderPoints": "",
        "removeOlderUnit": "3600",
        "cutout": 0,
        "colors": [
            "#1f77b4",
            "#00ff40",
            "#ff7f0e",
            "#ff0000",
            "#98df8a",
            "#d62728",
            "#ff9896",
            "#9467bd",
            "#c5b0d5"
        ],
        "x": 680,
        "y": 80,
        "wires": [
            [],
            []
        ]
    },
    {
        "id": "12a97e65.e56552",
        "type": "Input Split",
        "z": "dd9c4191.af407",
        "name": "",
        "inputProps": [
            "payload.data[0].date",
            "payload.data[0].data.energy.EPP0"
        ],
        "inputTopics": [
            "date",
            "epp0"
        ],
        "outputs": 2,
        "x": 420,
        "y": 580,
        "wires": [
            [
                "a6e9270.456bad8"
            ],
            [
                "3fd56cb1.1d86a4"
            ]
        ]
    },
    {
        "id": "a6e9270.456bad8",
        "type": "ui_text",
        "z": "dd9c4191.af407",
        "group": "2566d913.982b36",
        "order": 1,
        "width": "4",
        "height": "1",
        "name": "Data",
        "label": "Data",
        "format": "{{msg.payload}}",
        "layout": "row-spread",
        "x": 650,
        "y": 560,
        "wires": []
    },
    {
        "id": "3fd56cb1.1d86a4",
        "type": "ui_text",
        "z": "dd9c4191.af407",
        "group": "2566d913.982b36",
        "order": 2,
        "width": "4",
        "height": "1",
        "name": "EPP Suma",
        "label": "Liczydło P+ Suma",
        "format": "{{msg.payload}} kW",
        "layout": "row-spread",
        "x": 670,
        "y": 600,
        "wires": []
    },
    {
        "id": "5fb4c5f.35d583c",
        "type": "ui_gauge",
        "z": "dd9c4191.af407",
        "name": "",
        "group": "2566d913.982b36",
        "order": 4,
        "width": "4",
        "height": "3",
        "gtype": "gage",
        "title": "Prognoza mocy",
        "label": "kW",
        "format": "{{value}}",
        "min": 0,
        "max": "1.2",
        "colors": [
            "#00b500",
            "#e6e600",
            "#ca3838"
        ],
        "seg1": "0.8",
        "seg2": "1",
        "x": 800,
        "y": 180,
        "wires": []
    },
    {
        "id": "7152669d.676e18",
        "type": "ui_gauge",
        "z": "dd9c4191.af407",
        "name": "U1",
        "group": "9dbb2d7f.0c0db",
        "order": 1,
        "width": 0,
        "height": 0,
        "gtype": "gage",
        "title": "U1",
        "label": "V",
        "format": "{{value}}",
        "min": 0,
        "max": "470",
        "colors": [
            "#00b500",
            "#e6e600",
            "#ca3838"
        ],
        "seg1": "240",
        "seg2": "245",
        "x": 650,
        "y": 260,
        "wires": []
    },
    {
        "id": "8f9f45ba.13b448",
        "type": "ui_gauge",
        "z": "dd9c4191.af407",
        "name": "U2",
        "group": "e8096100.c5a08",
        "order": 1,
        "width": 0,
        "height": 0,
        "gtype": "gage",
        "title": "U2",
        "label": "V",
        "format": "{{value}}",
        "min": 0,
        "max": "470",
        "colors": [
            "#00b500",
            "#e6e600",
            "#ca3838"
        ],
        "seg1": "240",
        "seg2": "245",
        "x": 650,
        "y": 300,
        "wires": []
    },
    {
        "id": "73c944a2.cf58ec",
        "type": "ui_gauge",
        "z": "dd9c4191.af407",
        "name": "U3",
        "group": "9b7d58ea.52e548",
        "order": 1,
        "width": 0,
        "height": 0,
        "gtype": "gage",
        "title": "U3",
        "label": "V",
        "format": "{{value}}",
        "min": 0,
        "max": "470",
        "colors": [
            "#00b500",
            "#e6e600",
            "#ca3838"
        ],
        "seg1": "240",
        "seg2": "245",
        "x": 650,
        "y": 340,
        "wires": []
    },
    {
        "id": "d0721be6.971fd8",
        "type": "function",
        "z": "dd9c4191.af407",
        "name": "W -> kW",
        "func": "\nvar P = parseFloat(msg.payload) / 1000;\n\nP = P.toFixed(2);\n\nvar newMsg = { payload: P };\n\nreturn newMsg;",
        "outputs": 1,
        "noerr": 0,
        "x": 620,
        "y": 180,
        "wires": [
            [
                "5fb4c5f.35d583c"
            ]
        ]
    },
    {
        "id": "d6a9f6ca.36d5b8",
        "type": "function",
        "z": "dd9c4191.af407",
        "name": "mail",
        "func": "var msgStr = \"Dane:\\r\\n\";\n\nvar newMsg = \n   { \n       payload: msg.payload,\n       title: \"Licznik 96481317\",\n       bodytext: msgStr\n   }\n   \nreturn newMsg;",
        "outputs": 1,
        "noerr": 0,
        "x": 510,
        "y": 480,
        "wires": [
            [
                "71b32ac5.b534b4"
            ]
        ]
    },
    {
        "id": "71b32ac5.b534b4",
        "type": "debug",
        "z": "dd9c4191.af407",
        "name": "debug",
        "active": false,
        "console": "false",
        "complete": "payload",
        "x": 810,
        "y": 480,
        "wires": []
    },
    {
        "id": "dd0dfb64.5a4378",
        "type": "ui_text",
        "z": "dd9c4191.af407",
        "group": "2566d913.982b36",
        "order": 3,
        "width": 0,
        "height": 0,
        "name": "",
        "label": "P+ chwilowa",
        "format": "{{msg.payload}} kW",
        "layout": "row-spread",
        "x": 790,
        "y": 140,
        "wires": []
    },
    {
        "id": "dc3c131a.10967",
        "type": "function",
        "z": "dd9c4191.af407",
        "name": "W -> kW",
        "func": "\nvar P = parseFloat(msg.payload) / 1000;\n\nP = P.toFixed(2);\n\nvar newMsg = { payload: P };\n\nreturn newMsg;",
        "outputs": 1,
        "noerr": 0,
        "x": 620,
        "y": 140,
        "wires": [
            [
                "dd0dfb64.5a4378"
            ]
        ]
    },
    {
        "id": "505114e0.49b1ac",
        "type": "debug",
        "z": "dd9c4191.af407",
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "x": 130,
        "y": 165,
        "wires": []
    },
    {
        "id": "f464e111.78b9",
        "type": "ui_group",
        "z": "",
        "name": "Wykres P",
        "tab": "c76d7630.6dfab8",
        "order": 1,
        "disp": false,
        "width": "14"
    },
    {
        "id": "2566d913.982b36",
        "type": "ui_group",
        "z": "",
        "name": "Stany",
        "tab": "c76d7630.6dfab8",
        "order": 2,
        "disp": false,
        "width": "4"
    },
    {
        "id": "9dbb2d7f.0c0db",
        "type": "ui_group",
        "z": "",
        "name": "Column 1",
        "tab": "c76d7630.6dfab8",
        "order": 3,
        "disp": false,
        "width": "6"
    },
    {
        "id": "e8096100.c5a08",
        "type": "ui_group",
        "z": "",
        "name": "Column 2",
        "tab": "c76d7630.6dfab8",
        "order": 4,
        "disp": false,
        "width": "6"
    },
    {
        "id": "9b7d58ea.52e548",
        "type": "ui_group",
        "z": "",
        "name": "Column 3",
        "tab": "c76d7630.6dfab8",
        "order": 5,
        "disp": false,
        "width": "6"
    },
    {
        "id": "c76d7630.6dfab8",
        "type": "ui_tab",
        "z": "",
        "name": "Licznik 96481317",
        "icon": "dashboard",
        "order": 1
    }
]
Tak Nie Zaproponuj zmianę
Ostatnia aktualizacja 7 czerwca 2018
0 of 0 użytkowników uznało to za pomocne

6.2.Strażnik Mocy - biblioteka Plotly.js

Przykład 15-minutowego Strażnika Mocy Energii Elektrycznej wykorzystując bibliotekę Plotly.js

Instrukcja opcjonalnego dodania modułu Plotly.js do urządzenia Numeron znajduje się pod adresem https://docs.numeron.pl/node-red/#import-modulow-do-urzadzen

Pobierz plik Strażnik Mocy - biblioteka Plotly.js lub skopiuj poniższy kod:

[
    {
        "id": "974263be.d8d2c",
        "type": "tab",
        "label": "Strażnik Mocy",
        "disabled": false,
        "info": ""
    },
    {
        "id": "7da97b4.a468784",
        "type": "function",
        "z": "974263be.d8d2c",
        "name": "Chart Preparator P+ plotly.js Online",
        "func": "var maxSM = 800;\nif (context.global.get(\"maxSM\") !== undefined)\n{\n    maxSM = context.global.get(\"maxSM\");\n}\nvar multip = 1;\n\nif (context.global.get(\"multip\") !== undefined)\n{\n    multip = context.global.get(\"multip\");\n}\n\nif (context.global.get(\"dataSetGlobal\") !== undefined)\n{\n    dataSetGlobal = context.global.get(\"dataSetGlobal\");\n}\n\nif (!dataSet) {\n   var dataSet = [];\n}\nif (!dataSetGlobal) {\n   var dataSetGlobal = [];\n}\n\nvar dataSeries1 = {};\nvar dataSeries2 = {};\nvar dataSeries3 = {};\nvar dataSeries4 = {};\nvar dataSeries5 = {};\n\n        var tempDatax = [];\n        var tempDatay = [];\n        var tempDatax2 = [];\n        var tempDatay2 = [];\n        var tempDatax3 = [];\n        var tempDatay3 = [];\n        var tempDatax4 = [];\n        var tempDatay4 = [];\n        var tempDatax5 = [];\n        var tempDatay5 = [];        \n\n    tempDatax[0] = msg.payload.data[0].date;\n    tempDatay[0] = msg.payload.data[0].data.energy.PP * multip;\n    tempDatax2[0] = msg.payload.data[0].date;\n    tempDatay2[0] = msg.payload.data[0].data.energy.GrowingPower * multip;\n    tempDatax3[0] = msg.payload.data[0].date;\n    tempDatay3[0] = msg.payload.data[0].data.energy.PredictedPower * multip;\n    tempDatax4[0] = msg.payload.data[0].date;\n    tempDatay4[0] = msg.payload.data[0].data.energy.PP_L3 * multip;\n    tempDatax5[0] = msg.payload.data[0].date;\n    tempDatay5[0] = maxSM;    \n\ndataSeries1.x = tempDatax;\ndataSeries1.y = tempDatay;\ndataSeries1.type = 'scatter';\ndataSeries1.name = 'P+ SUM';\ndataSeries1.mode = 'lines';\ndataSeries2.x = tempDatax2;\ndataSeries2.y = tempDatay2;\ndataSeries2.type = 'bar';\ndataSeries2.name = 'Moc narastająca';\ndataSeries2.opacity = 1;\ndataSeries2.marker = {color: 'rgba(22, 180, 22, 1)'};\ndataSeries3.x = tempDatax3;\ndataSeries3.y = tempDatay3;\ndataSeries3.type = 'scatter';\ndataSeries3.mode = 'lines';\ndataSeries3.name = 'Prognoza';\ndataSeries4.x = tempDatax4;\ndataSeries4.y = tempDatay4;\ndataSeries4.type = 'scatter';\ndataSeries4.name = 'P+ L3';\ndataSeries4.mode = 'lines';\ndataSeries5.x = tempDatax5;\ndataSeries5.y = tempDatay5;\ndataSeries5.type = 'scatter';\ndataSeries5.name = 'Moc zamówiona';\ndataSeries5.line = {color: 'rgb(255, 255, 0)', width: 3};\ndataSeries5.mode = 'lines';\n\ndataSet.push(dataSeries1, dataSeries2);\n\nmsg.payload=dataSet;\nmsg.prognozax = dataSeries3.x[0];\nmsg.prognozay = dataSeries3.y[0];\nmsg.maxSM = maxSM;\n\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 460,
        "y": 60,
        "wires": [
            [
                "25300060.9c1b4"
            ]
        ]
    },
    {
        "id": "25300060.9c1b4",
        "type": "ui_template",
        "z": "974263be.d8d2c",
        "group": "3fc58583.6ceb4a",
        "name": "Straznik mocy plotly.js",
        "order": 1,
        "width": "13",
        "height": "10",
        "format": "<script src=\"https://node-red.numeron.pl/plotly-1.34.0.min.js\"></script>\n<div id=\"straznik\" style=\"min-width: 100%; min-height: 80%; margin: 0 auto\">\n<!-- Plotly chart will be drawn inside this DIV -->\n</div>\n<div id=\"dane\" style=\"min-width: 100%; min-height: 100px; margin: 0 auto\">\n    Czekam na dane...\n</div>\n<script>\n\n(function() \n{\n\n    var chartCanvasId = \"straznik\";\n    var maxSM;\n    var prognozax;\n    var prognozay;\n\n    var chartLayout = \n    {\n        xaxis: \n        {\n            type: 'date',\n            title: 'Czas',\n            fixedrange: true,\n            tickformat: '%H:%M\\r\\n%Y-%m-%d',\n            tickangle: 0,\n            hoverformat: '%H:%M:%S',\n        },\n        yaxis: \n        {\n            title: 'Moc W',\n            fixedrange: true,\n            rangemode: 'tozero',\n            anchor: 'x',\n            range: [0, 1000],\n            overlaying: 'y2',\n            dtick: 100,\n            tick0: 0\n        },\n        yaxis2: \n        {\n            title: null,\n            overlaying: 'n',\n            side: 'right',\n            fixedrange: true,\n            range: [0, 1000],\n            rangemode: 'tozero',\n            tick0: 0,\n            dtick: 100,\n            zeroline: false,\n            showline: false,\n            showticklabels: false,\n            showgrid: false\n        },\n        title: 'Strażnik Mocy',\n        showlegend: true,\n        legend: \n        {\n            x: 0,\n            y: 1.05,\n            orientation: 'h',\n        },\n        autosize: true,\n        font: {\n            family: 'BlinkMacSystemFont, Segoe UI, Roboto, Oxygen-Sans, Ubuntu, Cantarell, Helvetica Neue, sans-serif',\n            color: '#ffffff'\n            },\n        margin: \n        {\n            l: 50,\n            r: 25,\n            b: 50,\n            t: 70,\n            pad: 4\n        },\n        paper_bgcolor: '#363636',\n        plot_bgcolor: '#363636'\n    };\n    \n    var chartOptions = \n    {\n        displayModeBar: false, \n        displaylogo: false,\n        editable: false,\n        showLink: false,\n        scrollZoom: false\n    };\n\n    var chartDataSeries = null;\n    var gscope;\n    var initPlot = 0;\n    \n    function ShowChart()\n    {\n        if (chartDataSeries !== null)\n        {\n            var date = new Date();\n            date = new Date(date.getTime() - (date.getTimezoneOffset() * 60000));\n            var datefrom = new Date(Math.floor(new Date(date).getTime()/900000)*900000);\n            var datefromlate = datefrom;    \n            datefromlate.setSeconds(datefromlate.getSeconds() + 33);\n            datefrom = datefrom.toISOString().substr(0, 19).replace('T', ' ');\n            datefromlate = datefromlate.toISOString().substr(0, 19).replace('T', ' ');\n            var dateto = new Date(Math.ceil(new Date(date).getTime()/900000)*900000);\n            dateto = dateto.toISOString().substr(0, 19).replace('T', ' ');    \n            chartLayout.xaxis.range = [ datefrom, dateto ];\n            \n            if ((chartDataSeries[0].x.length == 1) && (initPlot == 0))\n            {\n                var tracemaxSM = {\n                x: [datefrom, datefrom],\n                y: [0, 0],\n                type: 'scatter',\n                name: 'Moc zamówiona',\n                line: {color: 'rgba(215, 215, 38, 1)', width: 1},\n                mode: 'lines',\n                opacity: 1,\n                fill: 'tozeroy',\n                fillcolor: 'rgba(215, 215, 38, 1)',\n                yaxis: 'y2'\n                };\n\n                var tracePrognoza = {\n                x: [prognozax, dateto],\n                y: [chartDataSeries[1].y[chartDataSeries[1].y.length -1], prognozay],\n                type: 'scatter',\n                name: 'Prognoza',\n                mode: 'lines',\n                line: {color: 'rgba(153, 73, 9, 1)', width: 3}\n                };\n            \n            chartDataSeries[3] = tracemaxSM;\n            chartDataSeries[2] = tracePrognoza;\n\n            maxRange = (parseInt(maxSM * 1.2 / 100) * 100) + 100;\n            chartLayout.yaxis.range = [ 0, maxRange ];\n            chartLayout.yaxis2.range = [ 0, maxRange ];\n            \n            Plotly.plot(chartCanvasId, chartDataSeries, chartLayout, chartOptions);\n            \n            Plotly.animate(chartCanvasId, {\n                data: [ {x: [datefrom, dateto],  y: [0, maxSM] } ],\n                traces: [3],\n                layout: {}\n            }, {\n                transition: {\n                duration: 2000,\n                easing: 'cubic-in-out'\n                }\n            })\n            \n            document.getElementById(\"dane\").innerHTML=\"<b>Moc chwilowa: </b>\" + chartDataSeries[0].y[chartDataSeries[0].y.length -1].toFixed(2) +\n            \"<br><b>Prognoza: </b>\" + chartDataSeries[2].y[chartDataSeries[2].x.length -1].toFixed(2) + \"<br><b>Moc zamówiona: </b>\" + maxSM.toFixed(2) +\n            \"<br><b>Zapas mocy: </b>\" + (maxSM - chartDataSeries[2].y[chartDataSeries[2].x.length -1]).toFixed(2);\n            \n            chartDataSeries = null;\n            initPlot = 1;\n            \n            } \n            else\n            if (chartDataSeries[0].x.length == 1)\n            {\n            Plotly.extendTraces(chartCanvasId, {\n            x:[\n               [chartDataSeries[0].x[chartDataSeries[0].x.length -1]],\n               [chartDataSeries[1].x[chartDataSeries[1].x.length -1]]\n              ],\n            y:[\n                [chartDataSeries[0].y[chartDataSeries[0].y.length -1]],\n                [chartDataSeries[1].y[chartDataSeries[1].y.length -1]]\n            ]}, [0,1]);\n            \n            var tracePrognoza = {\n                x: [prognozax, dateto],\n                y: [chartDataSeries[1].y[chartDataSeries[1].y.length -1], prognozay],\n                type: 'scatter',\n                name: 'Prognoza',\n                mode: 'lines',\n                line: {color: 'rgba(153, 73, 9, 1)', width: 3}\n            };\n            \n            maxRange = (parseInt(maxSM * 1.2 / 100) * 100) + 100;\n            var updateLayout = {'yaxis.range': [ 0, maxRange ], 'yaxis2.range': [ 0, maxRange ]};\n            Plotly.relayout(chartCanvasId, updateLayout);\n            var update = {x: [[prognozax, dateto]],  y: [[chartDataSeries[1].y[chartDataSeries[1].y.length -1], prognozay]] };\n            Plotly.restyle(chartCanvasId, update, [2]);\n            \n            var updateSM = {x: [[datefrom, dateto]],  y: [[0, maxSM]] };\n            Plotly.restyle(chartCanvasId, updateSM, [3]);\n            \n            document.getElementById(\"dane\").innerHTML=\"<b>Moc chwilowa: </b>\" + chartDataSeries[0].y[chartDataSeries[0].y.length -1].toFixed(2) +\n            \" <br><b>Prognoza: </b>\" + prognozay.toFixed(2) + \" <br><b>Moc zamówiona: </b>\" + maxSM.toFixed(2) +\n            \" <br><b>Zapas mocy: </b>\" + (maxSM - prognozay).toFixed(2);\n\n            if (prognozay.toFixed(2) > maxSM.toFixed(2))\n            {\n               var przekroczenie = Math.abs(maxSM - prognozay).toFixed(2);\n               przekroczenie = 'Alert z Node-Red! Prognozowane przekroczenie o ' + przekroczenie + 'W';\n               gscope.send({payload: \"sendSMS\", wiadomosc: przekroczenie}); \n            }\n            \n            }\n        }\n    };\n\n    (function(scope)\n    {\n        gscope = scope;\n        scope.$watch('msg', function(msg)\n        {\n            if (msg)\n            {\n                chartDataSeries = msg.payload;\n                maxSM = msg.maxSM;\n                prognozax = msg.prognozax;\n                prognozay = msg.prognozay;\n                setTimeout(ShowChart, 1000);\n            }\n        });\n    })(scope);\n})();    \n</script>\n\n",
        "storeOutMessages": false,
        "fwdInMessages": false,
        "templateScope": "local",
        "x": 720,
        "y": 60,
        "wires": [
            []
        ]
    },
    {
        "id": "4e5cb354.289aac",
        "type": "json",
        "z": "974263be.d8d2c",
        "name": "",
        "pretty": false,
        "x": 250,
        "y": 60,
        "wires": [
            [
                "7da97b4.a468784"
            ]
        ]
    },
    {
        "id": "2d1df23d.fba84e",
        "type": "udp in",
        "z": "974263be.d8d2c",
        "name": "proBox",
        "iface": "",
        "port": "1900",
        "ipv": "udp4",
        "multicast": "false",
        "group": "",
        "datatype": "buffer",
        "x": 80,
        "y": 60,
        "wires": [
            [
                "4e5cb354.289aac"
            ]
        ]
    },
    {
        "id": "3fc58583.6ceb4a",
        "type": "ui_group",
        "z": "",
        "name": "Strażnik Mocy",
        "tab": "d8b792ac.3d912",
        "disp": false,
        "width": "13",
        "collapse": false
    },
    {
        "id": "d8b792ac.3d912",
        "type": "ui_tab",
        "z": "",
        "name": "IIoT Numeron - Dashboard",
        "icon": "dashboard",
        "order": 2
    }
]
Tak Nie Zaproponuj zmianę
Ostatnia aktualizacja 7 czerwca 2018
0 of 0 użytkowników uznało to za pomocne

6.3.Prosty wykres mocy

Pobierz plik  Prosty wykres mocy lub skopiuj poniższy kod:

[
    {
        "id": "da120f98.f7424",
        "type": "tab",
        "label": "Prosty wykres mocy",
        "disabled": false,
        "info": ""
    },
    {
        "id": "f969d2ea.772ef",
        "type": "json",
        "z": "da120f98.f7424",
        "name": "",
        "pretty": false,
        "x": 230,
        "y": 100,
        "wires": [
            [
                "a8e0377d.8a7798",
                "fc927b8.b1a6b88",
                "1ead6a2d.932156",
                "8242451f.911708"
            ]
        ]
    },
    {
        "id": "fc927b8.b1a6b88",
        "type": "function",
        "z": "da120f98.f7424",
        "name": "Moc P+ L1",
        "func": "var P = parseFloat(msg.payload.data[0].data.energy.PP_L1);\nvar multip = 1;\nif (context.global.get(\"multip\") !== undefined)\n{\n    multip = context.global.get(\"multip\");\n}\nP = P * multip;\nP = P.toFixed(2);\n\nvar newMsg = { payload: P, topic:'P+ L1' };\n\nreturn newMsg;",
        "outputs": 1,
        "noerr": 0,
        "x": 444,
        "y": 49,
        "wires": [
            [
                "22a133f1.e4a8fc"
            ]
        ]
    },
    {
        "id": "1ead6a2d.932156",
        "type": "function",
        "z": "da120f98.f7424",
        "name": "Moc P+ L2",
        "func": "var P = parseFloat(msg.payload.data[0].data.energy.PP_L2);\nvar multip = 1;\nif (context.global.get(\"multip\") !== undefined)\n{\n    multip = context.global.get(\"multip\");\n}\nP = P * multip;\nP = P.toFixed(2);\n\nvar newMsg = { payload: P, topic:'P+ L2' };\n\nreturn newMsg;",
        "outputs": 1,
        "noerr": 0,
        "x": 444,
        "y": 89,
        "wires": [
            [
                "22a133f1.e4a8fc"
            ]
        ]
    },
    {
        "id": "8242451f.911708",
        "type": "function",
        "z": "da120f98.f7424",
        "name": "Moc P+ L3",
        "func": "var P = parseFloat(msg.payload.data[0].data.energy.PP_L3);\nvar multip = 1;\nif (context.global.get(\"multip\") !== undefined)\n{\n    multip = context.global.get(\"multip\");\n}\nP = P * multip;\nP = P.toFixed(2);\n\nvar newMsg = { payload: P, topic:'P+ L3' };\n\nreturn newMsg;",
        "outputs": 1,
        "noerr": 0,
        "x": 444,
        "y": 129,
        "wires": [
            [
                "22a133f1.e4a8fc"
            ]
        ]
    },
    {
        "id": "a8e0377d.8a7798",
        "type": "function",
        "z": "da120f98.f7424",
        "name": "Moc P+ SUMA",
        "func": "var P = parseFloat(msg.payload.data[0].data.energy.PP);\nvar multip = 1;\nif (context.global.get(\"multip\") !== undefined)\n{\n    multip = context.global.get(\"multip\");\n}\nP = P * multip;\nP = P.toFixed(2);\n\nvar newMsg = { payload: P, topic:'P+ SUM' };\n\nreturn newMsg;",
        "outputs": 1,
        "noerr": 0,
        "x": 454,
        "y": 169,
        "wires": [
            [
                "22a133f1.e4a8fc"
            ]
        ]
    },
    {
        "id": "22a133f1.e4a8fc",
        "type": "ui_chart",
        "z": "da120f98.f7424",
        "name": "",
        "group": "289045f7.9d9c9a",
        "order": 1,
        "width": "12",
        "height": "5",
        "label": "Moc P+ L1, L2, L3",
        "chartType": "line",
        "legend": "true",
        "xformat": "HH:mm:ss",
        "interpolate": "linear",
        "nodata": "czekam na dane online",
        "dot": false,
        "ymin": "",
        "ymax": "",
        "removeOlder": 1,
        "removeOlderPoints": "",
        "removeOlderUnit": "3600",
        "cutout": 0,
        "useOneColor": false,
        "colors": [
            "#aa5500",
            "#0080c0",
            "#00a800",
            "#ff8000",
            "#ff0000",
            "#d62728",
            "#ff9896",
            "#9467bd",
            "#c5b0d5"
        ],
        "useOldStyle": false,
        "x": 664,
        "y": 109,
        "wires": [
            [],
            []
        ],
        "inputLabels": [
            "wejscie"
        ]
    },
    {
        "id": "e06426e9.dd9208",
        "type": "udp in",
        "z": "da120f98.f7424",
        "name": "proBox",
        "iface": "",
        "port": "1900",
        "ipv": "udp4",
        "multicast": "false",
        "group": "",
        "datatype": "buffer",
        "x": 90,
        "y": 100,
        "wires": [
            [
                "f969d2ea.772ef"
            ]
        ]
    },
    {
        "id": "289045f7.9d9c9a",
        "type": "ui_group",
        "z": "",
        "name": "Prosty wykres mocy",
        "tab": "d8b792ac.3d912",
        "disp": false,
        "width": "12",
        "collapse": false
    },
    {
        "id": "d8b792ac.3d912",
        "type": "ui_tab",
        "z": "",
        "name": "IIoT Numeron - Dashboard",
        "icon": "dashboard",
        "order": 2
    }
]
Tak Nie Zaproponuj zmianę
Ostatnia aktualizacja 7 czerwca 2018
1 of 1 użytkowników uznało to za pomocne
Zaproponuj zmianę