top of page

Integracja urządzeń Modbus

IoT | Modbus | Odczyt i zapis cewek Modbus | Komputer brzegowy | JSON | Baza danych SQL | Grafana | Pulpity nawigacyjne w czasie rzeczywistym

Jednominutowa integracja Modbus do SQL z InDriver — łatwy samouczek

Dołącz do Jane z inanalytics.io, która zademonstruje szybką i wydajną integrację urządzenia Modbus z SQL, wszystko w ciągu zaledwie jednej minuty, wykorzystując potężne możliwości InDriver. Ten samouczek krok po kroku jest przeznaczony zarówno dla początkujących, jak i doświadczonych profesjonalistów, którzy chcą usprawnić proces integracji Modbus z SQL.

Przykład 1: Odczyt/zapis urządzenia Modbus, rejestrowanie Microsoft Azure i integracja pulpitu nawigacyjnego Grafana.

Integracja urządzeń Modbus z bazą danych SQL i Grafana przy użyciu InDriver

W tym rozwiązaniu InDriver, zainstalowany na komputerze z systemem Windows 11 Edge, zbiera dane z urządzenia Moxa IOLogic E1212 podłączonego przez Modbus TCP. Reprezentacja binarna wartości drugiej bieżącego znacznika czasu jest przechowywana w urządzeniu Moxa w 8-bajtowym wyjściu cewki co sekundę. Co 5 sekund urządzenie jest odczytywane, a dane są przechowywane w bazie danych SQL w formacie JSON.

Opis przykładowego algorytmu integracji Modbus

onStartup: Creating an SQL table if it doesn't exist and installing timer hooks.

Poniższe wiersze kodu:

  • Importuj ModbusApi z biblioteki obiektów komunikacji Modbus InDriver.

  • Utwórz tabelę „public.modbus” przy użyciu TSApi z kolumnami: source (tekst), ts (znacznik czasu) i data (JSON).

  • Usuń wszystkie wiersze zawierające dane z tabeli „public.modbus”, na potrzeby przykładu.

  • Zainstaluj haki, aby wyzwalać blok onHook co 1 sekundę (1000 ms) i co 5 sekund (5000 ms) synchronicznie z zegarem komputera.

  • Połącz się z urządzeniem Modbus „Moxa” o adresie 192.168.1.22.

InDriver.import('ModbusApi');

InDriver.sqlExecute("AzurePGSQL","select tsapicreatetable('public','modbus');");

InDriver.sqlExecute("AzurePGSQL","delete from public.modbus;");

InDriver.installHook(1000);

InDriver.installHook(5000);

ModbusApi.connectDevice( 'Moxa','{ "mode": "TCP", "networkAddress": "192.168.0.22"}');

onHook: Ustawianie cewek urządzenia Modbus co 1 sekundę, odczytywanie i rejestrowanie wartości cewek w tabeli SQL co 5 sekund.

Poniższe wiersze kodu:

  • Generuj tablicę z wartościami bitów reprezentującymi bieżącą wartość sekund co 1 sekundę, synchronicznie z zegarem (np. 00:00:01, 00:00:02 itd.), a następnie zapisz wygenerowaną tablicę w urządzeniu za pomocą ModbusApi.writeDevice ('Moxa', '{ "name": "coils", "type": "COILS", "address": 1, "data":' + JSON.stringify(array) + ' }'), który zapisuje do cewek od 1 do 8 bitów.

  • Odczytaj wartości cewek z urządzenia za pomocą ModbusApi.readDevice ('Moxa', '{"name": "coils", "type": "COILS", "address": 1, "size": 8}') co 5 sekund, zaloguj pobrane wartości w formacie JSON do tabeli SQL za pomocą InDriver.sqlExecute ("AzurePGSQL", ["select tsapiinsert('public','modbus','IOLogicE1212', '", ts.toUTCString(), "','", ModbusApi.getDeviceData ("Moxa"), "' );"]) i wyślij wiadomość do innych zadań InDriver zawierającą uzyskane wartości cewek Modbus.

if (InDriver.isHook(1000)) {

let seconds = ts.getSeconds()

InDriver.debug('write: ' + seconds)

let array = new Array(8)

for (var i = 0; i < 8; i++) {

array[i] = (seconds >> i) & 0x1

}

InDriver.debug('data: ' + JSON.stringify(array))

ModbusApi.writeDevice('Moxa','{ "name": "coils", "type": "COILS", "address": 1, "data":' + JSON.stringify(

array) + ' }')

}

if (InDriver.isHook(5000)) {

ModbusApi.readDevice( 'Moxa','{"name": "coils", "type": "COILS", "address":1, "size":8}')

let data = ModbusApi.getDeviceData("Moxa")

InDriver.debug("read: ",data)

let ts = InDriver.hookTs()

InDriver.sqlExecute("AzurePGSQL",["select tsapiinsert('public','modbus','IOLogicE1212', '", ts.toUTCString(), "','", data, "' );"])

InDriver.sendMessage(ts, '["device data","arch"]', data)

}

Wizualizacja danych Modbus w Grafana

Wizualizacja Modbus IO, tabela i szereg czasowy w Grafana

W Grafanie proces ten obejmuje umieszczanie wizualizacji i konfigurowanie zapytań SQL, jak pokazano poniżej.

W tym przykładzie zastosowano zarówno wizualizację tabeli, jak i szeregu czasowego. Wizualizacja tabeli obejmuje kolumny takie jak ts (znacznik czasu), sekundy (liczba całkowita) reprezentujące sekundy uzyskane z reprezentacji bitowej cewek oraz pojedyncze kolumny dla wartości cewek od 1 do 8.

Podobnie, wizualizacja szeregów czasowych wykorzystuje niemal identyczne zapytanie SQL, prezentując zmiany wartości cewek w czasie.

Edycja zapytania SQL w celu wyświetlenia Modbus IO na wykresie szeregu czasowego Grafana

Poniżej przedstawiono zapytanie SQL zastosowane w tabeli:

select ts,

(((data->'Moxa'->'Read'->'coils'->>'1'='true')::integer << 0) |

((data->'Moxa'->'Read'->'coils'->>'2'='true')::integer << 1) |

((data->'Moxa'->'Read'->'coils'->>'3'='true')::integer << 2) |

((data->'Moxa'->'Read'->'coils'->>'4'='true')::integer << 3) |

((data->'Moxa'->'Read'->'coils'->>'5'='true')::integer << 4) |

((data->'Moxa'->'Read'->'coils'->>'6'='true')::integer << 5) |

((data->'Moxa'->'Read'->'coils'->>'7'='true')::integer << 6) |

((data->'Moxa'->'Read'->'coils'->>'8'='true')::integer << 7)

) as seconds,

(data->'Moxa'->'Read'->'coils'->>'8'='true')::integer as "coil8",

(data->'Moxa'->'Read'->'coils'->>'7'='true')::integer as "coil7",

(data->'Moxa'->'Read'->'coils'->>'6'='true')::integer as "coil6",

(data->'Moxa'->'Read'->'coils'->>'5'='true')::integer as "coil5",

(data->'Moxa'->'Read'->'coils'->>'4'='true')::integer as "coil4",

(data->'Moxa'->'Read'->'coils'->>'3'='true')::integer as "coil3",

(data->'Moxa'->'Read'->'coils'->>'2'='true')::integer as "coil2",

(data->'Moxa'->'Read'->'coils'->>'1'='true')::integer as "coil1"

from modbus where source = 'IOLogicE1212' order by ts desc;

Przykład 2: Unikalna cecha InDriver — Jednoczesny odczyt wielu urządzeń Modbus

Schemat jednoczesnego odczytu urządzeń Modbus
Dane Modbus w formacie JSON

W tym scenariuszu trzy moduły Moxa IOLogic Ethernet I/O są połączone z komputerem brzegowym z InDriver. Wymagania systemowe obejmują równoczesny odczyt wejść dyskretnych ze wszystkich urządzeń, co zapewnia jednoczesne pobieranie danych, a nie sekwencyjne skanowanie.

Opis przykładowego algorytmu

onStartup: Podłączenie do trzech urządzeń Modbus i instalacja haka odczytu.

Poniższe wiersze kodu:

  • Importuj ModbusApi z biblioteki obiektów komunikacji Modbus InDriver.

  • Zainstaluj hak, aby wyzwalać blok onHook co 5 sekund (5000 ms) synchronicznie z zegarem komputera.

  • Połącz się z trzema urządzeniami Modbus „MoxaOne”, „MoxaTwo” i „MoxaThree” pod adresami 192.168.1.22 do 192.168.1.24

InDriver.import('ModbusApi');

InDriver.installHook(5000);

ModbusApi.connectDevice( 'MoxaOne','{ "mode": "TCP", "networkAddress": "192.168.0.22"}');

ModbusApi.connectDevice( 'MoxaTwo','{ "mode": "TCP", "networkAddress": "192.168.0.23"}');

ModbusApi.connectDevice( 'MoxaThree,'{ "mode": "TCP", "networkAddress": "192.168.0.24"}');

onHook: Jednoczesne odczytywanie dyskretnych danych wejściowych i rejestrowanie danych w SQL

Poniższe wiersze kodu:

  • Podobnie jak w przypadku transakcji SQL, ModbusApi oferuje bloki transakcji begin () i commit () dla funkcji odczytu i zapisu Modbus. Wszystkie funkcje w takim bloku są wykonywane jednocześnie po operacji commit () lub commitWait (). W tym przypadku obejmuje to równoczesne wykonywanie następujących funkcji odczytu ModbusApi: ModbusApi.readDevice('MoxaOne'.....) , ModbusApi.readDevice('MoxaTwo'.....) i ModbusApi.readDevice('MoxaThree'.....) .

  • Sprawdź ukończenie odczytu, używając ModbusApi.isSucceeded() . Po potwierdzeniu pobierz wszystkie odczytane dane, używając ModbusApi.getAllData() . Dane te można bez problemu zalogować do tabeli SQL, a źródło w tym przykładzie określono jako „3xIOLogicE1212”.

if (InDriver.isHook(5000)) {

ModbusApi.begin()

ModbusApi.readDevice( 'MoxaOne','{"name": "inputs", "type": "DISCRETEINPUTS", "address":1, "size":8}')

ModbusApi.readDevice( 'MoxaTwo','{"name": "inputs", "type": "DISCRETEINPUTS", "address":1, "size":8}')

ModbusApi.readDevice( 'MoxaThree','{"name": "inputs", "type": "DISCRETEINPUTS", "address":1, "size":8}')

ModbusApi.commitWait()

if (ModbusApi.isSucceeded()) {

let data = ModbusApi.getAllData()

let ts = InDriver.hookTs()

InDriver.sqlExecute("AzurePGSQL",["select tsapiinsert('public','modbus','3xIOLogicE1212', '", ts.toUTCString(), "','", data, "' );"])

InDriver.sendMessage(ts, '["device data","arch"]', data)

}

}

Blok kodu generuje zarejestrowane dane w formacie JSON, jak pokazano poniżej.
Odczyt odbywa się jednocześnie i zsynchronizowany z zegarem komputera , w regularnych odstępach 5-sekundowych, na przykład o godzinie 00:00:00, 00:00:05, 00:00:10 itd.

{  

„MoxaOne”: { „Odczyt”: { „dane wejściowe”: { „1”: prawda, „2”: fałsz, „3”: prawda, „4”: fałsz, „5”: prawda, „6”: fałsz, „7”: prawda, „8”: fałsz } } },  

„MoxaTwo”: { „Odczyt”: { „dane wejściowe”: { „1”: prawda, „2”: fałsz, „3”: prawda, „4”: fałsz, „5”: prawda, „6”: fałsz, „7”: prawda, „8”: fałsz } } },  

„MoxaThree”: { „Odczyt”: { „dane wejściowe”: { „1”: prawda, „2”: fałsz, „3”: prawda, „4”: fałsz, „5”: prawda, „6”: fałsz, „7”: prawda, „8”: fałsz } } }

}

bottom of page