55"""
66
77import os
8+ import sys
89import logging
910from flask import Flask , jsonify , request , render_template_string
1011from modapi .api .rtu import ModbusRTU
121122# Helper function to auto-detect RTU devices
122123def auto_detect (ports ):
123124 """Auto-detect Modbus RTU device on specified ports"""
124- if not ports :
125- return None
126-
127- # Try each port with common baudrates
128125 baudrates = [9600 , 115200 , 19200 , 4800 , 38400 , 57600 ]
129- unit_ids = [1 , 2 , 3 , 0 ] # Include broadcast address 0
126+ unit_ids = [1 , 2 , 3 , 4 ]
130127
131128 for port in ports :
132129 for baudrate in baudrates :
133130 for unit_id in unit_ids :
134131 try :
135- client = ModbusRTU (port = port , baudrate = baudrate , timeout = 0.5 )
136- if client .connect ():
137- # Try to read a register to verify connection
138- response = client .read_holding_registers (0 , 1 , unit_id )
139- if response is not None :
140- logger .info (f"Found working configuration: { port } , { baudrate } , unit_id={ unit_id } " )
141- client .disconnect ()
142- return {
143- 'port' : port ,
144- 'baudrate' : baudrate ,
145- 'unit_id' : unit_id
146- }
147-
148- # Try reading coils if registers didn't work
149- response = client .read_coils (0 , 8 , unit_id )
150- if response is not None :
151- logger .info (f"Found working configuration: { port } , { baudrate } , unit_id={ unit_id } " )
152- client .disconnect ()
153- return {
154- 'port' : port ,
155- 'baudrate' : baudrate ,
156- 'unit_id' : unit_id
157- }
158-
132+ client = ModbusRTU (port , baudrate )
133+ logger .info (f"Testing configuration: port={ port } , baudrate={ baudrate } , unit_id={ unit_id } " )
134+
135+ # Próbuj odczytać rejestry
136+ logger .debug (f"Attempting to read holding registers with unit_id={ unit_id } " )
137+ response = client .read_holding_registers (0 , 1 , unit_id )
138+ if response is not None :
139+ logger .info (f"✅ Auto-detect success with holding registers: port={ port } , baudrate={ baudrate } , unit_id={ unit_id } , response={ response } " )
140+ client .disconnect ()
141+ return {
142+ 'port' : port ,
143+ 'baudrate' : baudrate ,
144+ 'unit_id' : unit_id
145+ }
146+ else :
147+ logger .debug (f"No response from holding registers with unit_id={ unit_id } " )
148+
149+ # Próbuj odczytać cewki
150+ logger .debug (f"Attempting to read coils with unit_id={ unit_id } " )
151+ response = client .read_coils (0 , 8 , unit_id )
152+ if response is not None :
153+ logger .info (f"✅ Auto-detect success with coils: port={ port } , baudrate={ baudrate } , unit_id={ unit_id } , response={ response } " )
159154 client .disconnect ()
155+ return {
156+ 'port' : port ,
157+ 'baudrate' : baudrate ,
158+ 'unit_id' : unit_id
159+ }
160+ else :
161+ logger .debug (f"No response from coils with unit_id={ unit_id } " )
162+
163+ client .disconnect ()
160164 except Exception as e :
161- logger .debug (f"Error testing { port } at { baudrate } with unit_id={ unit_id } : { e } " )
165+ # Log connection errors
166+ logger .debug (f"Error testing { port } at { baudrate } baud with unit_id={ unit_id } : { e } " )
162167
163168 logger .warning ("No working configuration found" )
164169 return None
165170
171+ def init_mock_mode ():
172+ """Initialize mock mode for testing without hardware"""
173+ global RTU_CONFIG
174+ print ("🔧 Uruchamiam w trybie MOCK (bez rzeczywistego urządzenia)" )
175+ RTU_CONFIG = {
176+ 'port' : 'MOCK' ,
177+ 'baudrate' : 9600 ,
178+ 'unit_id' : 1
179+ }
180+ logger .info (f"✅ Używam konfiguracji MOCK: { RTU_CONFIG } " )
181+
182+ # Monkey patch ModbusRTU for mock mode
183+ def mock_read_coils (self , unit_id , address , count ):
184+ logger .info (f"MOCK: Reading { count } coils from address { address } (unit_id={ unit_id } )" )
185+ return [False ] * count
186+
187+ def mock_write_single_coil (self , unit_id , address , value ):
188+ logger .info (f"MOCK: Writing coil at address { address } to { value } (unit_id={ unit_id } )" )
189+ return True
190+
191+ def mock_read_holding_registers (self , unit_id , address , count ):
192+ logger .info (f"MOCK: Reading { count } registers from address { address } (unit_id={ unit_id } )" )
193+ return [0 ] * count
194+
195+ ModbusRTU .read_coils = mock_read_coils
196+ ModbusRTU .write_single_coil = mock_write_single_coil
197+ ModbusRTU .read_holding_registers = mock_read_holding_registers
198+
199+ # Override connect and disconnect for mock mode
200+ ModbusRTU .connect = lambda self : True
201+ ModbusRTU .disconnect = lambda self : None
202+
203+ print ("✅ Mock RTU device ready" )
204+ return True
205+
166206def init_rtu ():
167207 """Inicjalizuj RTU i znajdź działającą konfigurację"""
168208 global RTU_CONFIG
@@ -183,7 +223,33 @@ def init_rtu():
183223 manual_client = ModbusRTU ('/dev/ttyACM0' , 9600 )
184224
185225 if manual_client .connect ():
186- success , result = manual_client .test_connection (1 )
226+ # Implement test_connection directly
227+ result = {
228+ 'port' : '/dev/ttyACM0' ,
229+ 'baudrate' : 9600 ,
230+ 'unit_id' : 1 ,
231+ 'success' : False ,
232+ 'error' : None
233+ }
234+
235+ try :
236+ # Try to read a register to verify connection
237+ response = manual_client .read_holding_registers (0 , 1 , 1 )
238+ if response is not None :
239+ result ['success' ] = True
240+ else :
241+ result ['error' ] = "No response from device"
242+
243+ # Try reading coils if registers didn't work
244+ if not result ['success' ]:
245+ response = manual_client .read_coils (0 , 8 , 1 )
246+ if response is not None :
247+ result ['success' ] = True
248+ result ['error' ] = None
249+ except Exception as e :
250+ result ['error' ] = str (e )
251+
252+ success = result ['success' ]
187253 if success :
188254 RTU_CONFIG = {
189255 'port' : '/dev/ttyACM0' ,
@@ -212,7 +278,33 @@ def status():
212278
213279 # Test połączenia
214280 with ModbusRTU (RTU_CONFIG ['port' ], RTU_CONFIG ['baudrate' ]) as client :
215- success , result = client .test_connection (RTU_CONFIG ['unit_id' ])
281+ # Implement test_connection directly
282+ result = {
283+ 'port' : RTU_CONFIG ['port' ],
284+ 'baudrate' : RTU_CONFIG ['baudrate' ],
285+ 'unit_id' : RTU_CONFIG ['unit_id' ],
286+ 'success' : False ,
287+ 'error' : None
288+ }
289+
290+ try :
291+ # Try to read a register to verify connection
292+ response = client .read_holding_registers (0 , 1 , RTU_CONFIG ['unit_id' ])
293+ if response is not None :
294+ result ['success' ] = True
295+ else :
296+ result ['error' ] = "No response from device"
297+
298+ # Try reading coils if registers didn't work
299+ if not result ['success' ]:
300+ response = client .read_coils (0 , 8 , RTU_CONFIG ['unit_id' ])
301+ if response is not None :
302+ result ['success' ] = True
303+ result ['error' ] = None
304+ except Exception as e :
305+ result ['error' ] = str (e )
306+
307+ success = result ['success' ]
216308
217309 return jsonify ({
218310 'connected' : success ,
@@ -340,31 +432,30 @@ def get_register(address):
340432 print ("🚀 RTU Output Server - Zastępuje problematyczny run_output.py" )
341433 print ("📡 Używa bezpośredniej komunikacji RTU zamiast PyModbus" )
342434
343- # Inicjalizuj RTU
344- if init_rtu ():
345- print (f"✅ RTU skonfigurowane: { RTU_CONFIG ['port' ]} @ { RTU_CONFIG ['baudrate' ]} baud" )
346- print (f"🔧 Unit ID: { RTU_CONFIG ['unit_id' ]} " )
347- print ("🌐 Serwer dostępny na http://localhost:5005" )
348- print ("📋 API endpoints:" )
349- print (" GET /status - status połączenia" )
350- print (" GET /coil/<addr> - odczyt cewki" )
351- print (" POST /coil/<addr> - zapis cewki" )
352- print (" GET /coils - odczyt wszystkich cewek" )
353- print (" GET /registers/<addr> - odczyt rejestru" )
354- print ()
355-
356- # Uruchom serwer Flask
357- app .run (
358- host = '0.0.0.0' ,
359- port = 5005 ,
360- debug = False , # Wyłącz debug w produkcji
361- use_reloader = False # Zapobiega podwójnej inicjalizacji
362- )
435+ # Import sys if not already imported
436+ import sys
437+
438+ # Check for mock mode
439+ mock_mode = "--mock" in sys .argv
440+
441+ if mock_mode :
442+ print ("🧪 Wykryto flagę --mock, uruchamiam w trybie testowym bez sprzętu" )
443+ init_success = init_mock_mode ()
363444 else :
445+ # Inicjalizacja RTU
446+ print ("🔌 Uruchamiam w trybie normalnym, szukam podłączonego sprzętu RTU" )
447+ init_success = init_rtu ()
448+
449+ if not init_success :
364450 print ("❌ Nie można uruchomić serwera bez działającej konfiguracji RTU" )
365451 print ("🔍 Sprawdź:" )
366452 print (" - Czy urządzenie jest podłączone do /dev/ttyACM0 lub /dev/ttyUSB0" )
367- print (" - Czy urządzenie jest włączone" )
453+ print (" - Czy urządzenie jest włączone" )
368454 print (" - Czy masz uprawnienia do portu szeregowego" )
369455 print (" - Czy nie używa niestandardowej prędkości lub unit ID" )
370- exit (1 )
456+ print ("\n 💡 Możesz uruchomić w trybie MOCK dla testów: python run_rtu_output.py --mock" )
457+ sys .exit (1 )
458+
459+ # Uruchom serwer
460+ print (f"✅ Uruchamiam serwer na http://localhost:5005/" )
461+ app .run (host = '0.0.0.0' , port = 5005 , debug = False , use_reloader = False )
0 commit comments