Created At

Jun 28, 2026

Last Update

Jun 30, 2026

Platforms

HC 3 Lite, Yubii Home Pro, Yubii Home, HC 3

Views

74

Download

8

Type Quick App

1. Overview

This premium integrator utility is designed to eliminate the tedious, manual process of map-probing Modbus gateways and slave devices (meters, PLCs, HVAC, sensors). Instead of guessing addresses, this QuickApp establishes an automated, high-speed sequential polling loop directly inside Fibaro. It handles native multi-byte data pairing, identifies active registers, filters duplicates, and automatically scans the network to find hidden Slave Unit IDs, delivering near-zero latency and unprecedented visibility into your industrial and smart home Modbus infrastructure.

2. Key Features

  • High-Speed Block Scanning (Func 03 & 04): Optimized to poll consecutive registers in custom chunk sizes (up to 125 registers per frame). Seamlessly switches between Read Holding Registers (03) and Read Input Registers (04) via the UI dashboard.

  • Native IEEE754 32-Bit Float Decoding: Utilizes advanced Lua 5.3 bitwise processing paired with native C-struct unpacking (string.unpack). Automatically parses raw registers into standard Int16, Hex, and complex 32-bit Floats across both ABCD and CDAB byte-swapping profiles for seamless cross-manufacturer mapping.

  • Automated Slave ID Discovery (1–255): Includes a dedicated auto-discovery scan engine. Pings every Unit ID from 1 to 255 sequentially, evaluating response packets and CRC validation to locate all active Modbus hardware nodes automatically.

  • Safe Watchdog Engine & Anti-Freeze Design: Enforces a strict 1000ms explicit connection timeout watchdog utilizing independent asynchronous scheduling (fibaro.clearTimeout paired with fibaro.setTimeout). Guarantees the Home Center UI and main thread never hang or freeze even when the target TCP gateway becomes unreachable.

  • Deep Telemetry & Error Analytics: Tracks and breaks down network performance in real-time. Dynamically exposes Found Data Blocks, Empty Values, Illegal Address Exceptions (Modbus Exception 0x02), and Checksum (CRC) Frame Errors.

  • Real-Time Data Grouping & Duplication Filter: Analyzes telemetry logs, highlights active continuous block regions, and separates unique values from redundant/duplicate register entries to simplify data mapping.

  • Interactive On-Screen Commissioning: Allows installers to increment/decrement target Modbus IDs, modify scan boundaries (End Registers), and toggle functions directly through UI buttons without opening the variable configuration panel.

3. UI Breakdown & Visuals

  • Scan Engine Control (ON / OFF): Main system toggles serving as Start Scan and Stop Scan controls with instant visual status feedback.

  • Interactive Variable Adjusters: Dynamic layout elements (lblModbusID, lblScanID, lblEndReg, lblFuncCode) providing instantaneous feedback as you click buttons to step through Modbus IDs, scan modes, or boundaries.

  • Live Data & Hex Monitor (lblData): Displays a structured, multi-line telemetry sheet rendering target registers, accurate decimal values, hexadecimal translations, and interpreted Int16 conversions.

  • Duplicate Registers Alert Console (lblDupRegs): A smart diagnostic window compiling all overlapping data paths to help you spot mirrors and shared memory registers instantly.

  • Automatic Node Mapping Panel (lblSlaveID / lblMasterID): Displays real-time diagnostic output during automated scan sequences, visualizing ping progress and compiling the final active Slave list.

4. Variables Configuration

After importing the .fqa/.fqax file into your Fibaro Home Center, please configure the following parameters within the device variables panel:

Variable Name Default Value Description
ipZlan 192.168.1.252 The local LAN IP address of your Modbus TCP Gateway or end device.
portZlan 5002 The standard TCP communication port utilized by your Modbus network converter.
idModbus 1 Target Modbus Slave Unit ID to scan.
startReg 1 The starting register address for the diagnostic block sequence.
endReg 150 The final boundary register address to conclude the scan loop.
funcCode 4 Modbus standard Function Code (3 = Holding Registers, 4 = Input Registers).
scanDelay 150 Inter-frame delay in milliseconds between consecutive requests to prevent gateway overload.
blockSize 20 Max count of registers requested per RTU packet frame (Standard limit up to 125).

5. Quick Installation Guide

  • Step 1: Download the QuickApp binary configuration file (SCAN_Modbus_RTU_Eng.fqax) to your computer.

  • Step 2: Log into your Fibaro Home Center, navigate to Settings -> Devices -> Click Add Device -> Choose Other Device -> Click Upload File and select your downloaded asset.

  • Step 3: Open your newly created scanner device, navigate to the Variables tab, fill in your gateway parameters (ipZlan, portZlan, idModbus, endReg), and click Save.

  • Step 4: Trigger the scan via the UI dashboard. Check your live console or debug logs to observe real-time data pairing and network mapping analytics.

  • Step 5: How to scan:

4 Comments,  Want to add comment please login
Bc2c88dfdb16258714efcea63003473c

Hi Andrzej, Thanks for pointing this out. You were absolutely right — the previous reassembly logic introduced a regression by assuming the response length from the request size. I've now refactored the TCP receive logic into a proper stream parser. Instead of waiting for a fixed length, it determines the frame size dynamically from the response itself (Exception = 5 bytes, FC03/FC04 = 3 + ByteCount + 2), so exception frames and shorter valid responses are handled correctly again. The receive buffer is also now persistent across reads, consuming one complete frame at a time while preserving any remaining bytes in the TCP stream. Thanks again for catching this regression. It led to a much cleaner and more robust implementation.

A76a3a4e1774cd33f5471b7ec24d0d428

New problem — a regression introduced by the reassembly logic This is the most important thing to fix. The reassembly mechanism relies on the condition #receiveBuffer >= expectedLength, where in the block scan expectedLength = 3 + count*2 + 2 (it assumes a full, successful response). The problem: if the device replies with an exception frame (e.g. Illegal Address 0x02), that frame is only 5 bytes long. With a 20-register block, expectedLength is 45, so the condition 5 >= 45 is never satisfied → the readLoop keeps waiting for the rest of the data that never arrives → the watchdog only kills it after 1500 ms as a timeout. Consequences: "Illegal Address" detection in the block scan no longer works — exceptions are now counted as timeouts, and the code in parseResponse that handles fCode >= 0x80 is effectively unreachable. The same mechanism breaks the "device returns fewer registers than requested" fail-safe — a shorter-than-expected but valid frame will also never reach expectedLength and ends in a timeout. On a device with sparsely populated registers, every such block now costs a full 1.5 s — the scan can take a very long time.

Bc2c88dfdb16258714efcea63003473c

Hi Andrzej, Thank you so much for taking the time to review the code. Your insights are incredibly accurate and highlight some critical flaws in how the QuickApp handles TCP/IP and Modbus addressing. You are absolutely right that treating TCP as a packet-based protocol rather than a stream, and failing to manage sockets properly, are recipes for disaster on an OT network. Based on your feedback, I have refactored the code to address these issues: 1. Persistent TCP Connection & Socket Leak Fix: Instead of opening a new socket for every single request, the app now establishes a persistent connection when scanning starts and properly calls sock:close() upon completion or whenever a connect_error/timeout occurs. This prevents socket exhaustion and avoids hammering the gateway. 2. 0-based Register Addressing: I've added a -1 offset when building the RTU frame so that user-facing inputs (1-based) align correctly with Modbus wire addresses (0-based). 3. TCP Reassembly / Buffered Reading: I've introduced a basic receiveBuffer to accumulate incoming TCP fragments until the expected Modbus RTU frame length is met, preventing dropped data on larger block sizes. 4. Live Stats Update: self:refreshStats() is now explicitly called inside the processing loop so the UI updates in real-time during the scan. 5. Auto Scan Slave Delay: Increased the delay and added a warning mechanism to prevent aggressive 50ms polling from crashing shared RS-485 networks. Here is the updated core logic implementing your suggestions. Thanks again for the pro-level review!

A76a3a4e1774cd33f5471b7ec24d0d428

Potencial problems Register addressing (1-based vs 0-based). The scan starts at register 1 and puts 0x0001 on the wire. Modbus wire addresses are 0-based, so what a device datasheet calls "register 1" (40001) usually sits at wire address 0. Readings can therefore be off by one relative to what you expect — keep this in mind when interpreting results. No TCP reassembly. sock:read reads only once. If a response arrives split across multiple TCP packets, the code (correctly) rejects the frame on a length mismatch, but the data for that whole block is lost. With 20-register blocks this is a real risk on some gateways; reducing blockSize works around it. A new socket per request. Every read opens and closes a separate TCP connection. Many ZLAN-type gateways accept only one client and release the socket slowly, so rapid requests (50–150 ms apart) can produce "connection refused" errors. If the scan stalls, increase the delays. Stats don't update live. The timeout/"Empty" counter is never incremented, and refreshStats() is never actually called during a scan, so the statistics line doesn't refresh while scanning. Cosmetic only. Inconsistent endReg default. The QuickApp variable is 500, but initVariables and resetSettings use 150. Harmless, but confusing. Socket not closed on connect failure. The connect_error path doesn't call sock:close() or clearTimeout. When mass-scanning toward an unreachable gateway, sockets can briefly accumulate. binarySwitch device type. Because the app is a binary switch, accidentally turning the device "on" (from a scene or a voice assistant) will launch a full scan. Don't include it in scenes. Operational limitation (not a code bug). The "FIND ID SLAVE" routine sends 255 requests at 50 ms intervals. On a shared RS-485 bus that another master (PLC/SCADA) is already polling, this aggressive scanning can cause collisions and disrupt live communication — so it shouldn't be run on a production OT network while it's in use.

Load more comments
© 2024. Nice-Polska Sp. z o.o.Privacy policyTerms & ConditionsFeedback