Życzymy Państwu Nowego Roku pełnego innowacji, sukcesów i nieograniczonych możliwości.
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.
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
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.
Below is the SQL query applied in Table:
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
In this scenario, three Moxa IOLogic Ethernet I/O modules are linked to an Edge Computer with InDriver. The system requirement is to concurrently read the Discrete Inputs from all devices, ensuring simultaneous data retrieval rather than sequential scanning.
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 } } }
}