Witam wszystkich. Jestem nowy na forum i od pewnego czasu próbuję ogarnąć Node Reda w Home Assistant. W swojej instalacji mam 3 moduły przekaźników Waveshare po 32 kanały sterowane przez Modbus RTU. Sam proces uruchamiania poszczególnych kanałów mam ogarnięty. Problem pojawił się przy odczycie stanów przekaźników. Do odczytu używam noda Modbus Getter (FC 01 read coil) i po uruchomieniu kanału 0 i odczytaniu stanów przekaźników otrzymuję informację, że uruchomiony jest przekaźnik 24 kiedy w rzeczywistości prawidłowo uruchomiony jest pierwszy przekaźnik.
Zrobiłem tablicę wszystkich sygnałów i wychodzi mi na to, że nod odczytuje te tablicę 32 wartości bitowych jakby była zmienną 32 bitową i to z przestawionymi bajtami ( powiedzmy zamiast LSB mam MSB). Przeszukałem internet i znalazłem, że do przesunięć bajtów można użyć noda buffer parser, lecz próbowałem różnych konfiguracji i nie mogę sobie poradzić… Czy ktoś miał podobny problem?
Cewki 1-8 to pierwszy bajt, w kolejnośći od prawej do lewej.
Cewki 9- 17 w drugim bajcie .. itd.
W konsekwencji dla 32 bitów, w twojm przypadku cewka 1 wyląduje w pierszym odczytanim bajcie na najmłodszej pozycji.
Kolejno cewki bit po bicie to wyglądają tak:
08 07 06 05 04 03 02 01
16 15 14 13 12 11 10 09
24 23…. itd
32 31….
To jest twoja odczytana tablica, ale gdy tą tablice potraktujesz jako jedna liczbę 32 bitową ( czyli jakbyś zapisał to w jednej linii) masz wrażenie, że wszystko jest wymieszane.
Dla słowa 32 bitowego wygląda to tak jakby było na 24 a np. 32 cewka będzie na pozycji 8. Wszystko gra tylko odczytane traktuj jako typu byte a nie integer. Źle interpretujesz to co dostajesz.
Dlatego ten nod nie jest dla początkującego prosty a dla wprawionego bezużyteczny - bo ma pewne ograniczenia..
Wystarczy napisać prostą funkcję, która będzie parsować taki bufor w pętli:
Gotowy kod dla węzła function . Zakłada on, że na wejściu (msg.payload) otrzymujesz surowy bufor (Buffer) zawierający 4 bajty danych z odczytu Modbus, a funkcja wysyła 32 osobne wiadomości w sposób asynchroniczny (msg.topic, msg.payload).
// Sprawdzenie, czy payload jest buforem i ma odpowiednią długość
if (!Buffer.isBuffer(msg.payload) || msg.payload.length < 4) {
node.error("Wejściowy payload musi być buforem o długości minimum 4 bajtów.");
return null;
}
const totalCoils = 32;
const startAddress = 0; // adres startowy cewki Modbus (domyślnie 0)
// Pętla iterująca po wszystkich 32 cewkach
for (let i = 0; i < totalCoils; i++) {
// Określenie, w którym bajcie (0-3) znajduje się dana cewka
const byteIndex = Math.floor(i / 8);
// Określenie pozycji bitu (0-7) wewnątrz danego bajtu
const bitIndex = i % 8;
// Pobranie wartości konkretnego bitu (operacja logicznego AND z maską bitową)
const coilState = (msg.payload[byteIndex] & (1 << bitIndex)) !== 0;
// Obliczenie rzeczywistego numeru cewki
const coilNumber = startAddress + i;
// Tworzenie nowego, niezależnego obiektu wiadomości (wymagane przy asynchroniczności)
const newMsg = {
topic: `Cewka ${coilNumber}`,
payload: coilState
};
// Asynchroniczne wysłanie wiadomości za pomocą wbudowanej metody node.send
node.send(newMsg);
}
// Zwracamy null na końcu, aby zablokować standardowe (synchroniczne) wyjście z węzła
return null;
Dziękuje za pomoc Robinl30. Dzięki kodowi podanemu przez Ciebie udało się odczytać wszystkie cewki po kolei, lecz w odwrotnej kolejności, ale z tym sobie poradziłem Nie mniej jednak tego właśnie potrzebowałem.
Teraz powstaje pytanie jak odczytać pojedynczą cewkę w home assistant. Docelowo chciałbym widzieć, które przekaźniki są załączone.