-
Notifications
You must be signed in to change notification settings - Fork 8
Stability fixes for discovery and reconnection #83
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,7 +6,7 @@ | |
| const KNXInterface = require('./KNXInterface'); | ||
|
|
||
| // 3 minute search loop | ||
| // const FIND_DEVICES_INTERVAL = 3 * (60 * 1000); | ||
| const FIND_DEVICES_INTERVAL = 3 * (60 * 1000); | ||
|
|
||
| class KNXInterfaceManager extends EventEmitter { | ||
|
|
||
|
|
@@ -16,8 +16,8 @@ | |
| this.homey = homey; | ||
|
|
||
| // Formatted logging | ||
| this.log = console.log.bind(this, '[KNX interface manager]'); | ||
| this.errorLog = console.error.bind(this, '[KNX interface manager] ERROR:'); | ||
|
|
||
| // search running status | ||
| this.searchRunning = false; | ||
|
|
@@ -25,7 +25,7 @@ | |
| this.KNXInterfaces = {}; | ||
|
|
||
| if (ip.isV4Format(localIP)) { | ||
| this.localIPBuffer = ip.toBuffer(ip.address()); | ||
| this.localIPBuffer = ip.toBuffer(localIP); | ||
| const interfaces = this.homey.settings.get('interfaces') || []; | ||
|
|
||
| this.findKNXInterfaces() | ||
|
|
@@ -48,12 +48,12 @@ | |
| return; | ||
| } | ||
|
|
||
| // this.findDevicesInterval = setInterval(() => { | ||
| // this.findKNXInterfaces() | ||
| // .catch(error => { | ||
| // this.log('findKNXinterfaces error', error); | ||
| // }); | ||
| // }, FIND_DEVICES_INTERVAL); | ||
| this.findDevicesInterval = setInterval(() => { | ||
| this.findKNXInterfaces() | ||
| .catch((error) => { | ||
| this.log('findKNXinterfaces error', error); | ||
| }); | ||
| }, FIND_DEVICES_INTERVAL); | ||
|
Comment on lines
+51
to
+56
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The fact that this was here already but commented out makes me wonder why. Was there a good reason for not doing it like this?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could not find a good reason. It was disabled over 5 years ago so no way to know |
||
|
|
||
| // Respond on an emit. Add the found interface to the list of interfaces. | ||
| this.on('interface_found', (knxInterface) => { | ||
|
|
@@ -207,7 +207,7 @@ | |
| udpSocket | ||
| .on('error', (err) => { | ||
| // If the udp server errors, close the connection | ||
| console.error('udp server error:', err.stack); | ||
| try { | ||
| udpSocket.close(); | ||
| } catch (e) { | ||
|
|
@@ -220,10 +220,9 @@ | |
| // When an message is received, parse it for KNXIP data | ||
| const knxInterface = this.parseKNXResponse(msg); | ||
| if (!knxInterface) { | ||
| return reject(new Error('No valid KNXnet response')); | ||
| return null; // Skip non-KNX messages, keep listening for valid responses | ||
| } | ||
|
Comment on lines
221
to
224
|
||
| // If the data was valid, emit the found interface | ||
| // here should be an extra catch to handle other not search/check related KNX messages | ||
| try { | ||
| if (this.KNXInterfaces[knxInterface.interfaceMac]) { | ||
| this.log('Updating', knxInterface.interfaceName); | ||
|
|
@@ -238,10 +237,8 @@ | |
| this.homey.settings.set('interfaces', interfaces); | ||
|
|
||
| this.emit('interface_found', this.KNXInterfaces[knxInterface.interfaceMac]); | ||
| return resolve(this.KNXInterfaces[knxInterface.interfaceMac]); | ||
| } catch (error) { | ||
| this.log('Creating IP interface instance failed: ', error); | ||
| reject(error); | ||
| } | ||
| return null; | ||
| }) | ||
|
|
@@ -288,7 +285,6 @@ | |
| - Send the description request to obtain the device information | ||
| These actions mimics the traffic that ETS uses to check a IP interface | ||
| */ | ||
| this.interfaceFound = false; | ||
| if (this.searchRunning === false) { | ||
| this.log('Checking if', ipAddress, 'is a KNX IP interface'); | ||
| this.searchRunning = true; | ||
|
|
@@ -319,10 +315,12 @@ | |
| const udpSocket = dgram.createSocket('udp4'); // Create the socket connections | ||
|
|
||
| return new Promise((resolve, reject) => { | ||
| let interfaceFound = false; | ||
|
|
||
| udpSocket | ||
| .on('error', (err) => { | ||
| // If the udp server errors, close the connection | ||
|
Comment on lines
315
to
322
|
||
| console.error('UDP server error', err.stack); | ||
| try { | ||
| udpSocket.close(); | ||
| } catch (e) { | ||
|
|
@@ -361,12 +359,16 @@ | |
| } catch (e) { | ||
| // socket may already be closed | ||
| } | ||
| this.interfaceFound = true; | ||
| interfaceFound = true; | ||
| this.searchRunning = false; | ||
|
|
||
|
Comment on lines
359
to
364
|
||
| try { | ||
| // Use the Interface MAC as the key value | ||
| this.KNXInterfaces[knxInterface.interfaceMac] = new KNXInterface(knxInterface); | ||
| // Update existing interface or create a new one | ||
| if (this.KNXInterfaces[knxInterface.interfaceMac]) { | ||
| this.KNXInterfaces[knxInterface.interfaceMac].updateIP(knxInterface.interfaceIp); | ||
| } else { | ||
| this.KNXInterfaces[knxInterface.interfaceMac] = new KNXInterface(knxInterface); | ||
| } | ||
| const interfaces = this.getSimpleInterfaceList(); | ||
| this.homey.settings.set('interfaces', interfaces); | ||
| this.emit('interface_found', this.KNXInterfaces[knxInterface.interfaceMac]); | ||
|
|
@@ -389,7 +391,7 @@ | |
| .bind(36711); | ||
|
|
||
| setTimeout(() => { | ||
| if (!this.interfaceFound) { | ||
| if (!interfaceFound) { | ||
| try { | ||
| udpSocket.close(); | ||
| } catch (error) { | ||
|
Comment on lines
391
to
397
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The periodic discovery interval is started in the constructor but there’s no corresponding cleanup (e.g., clearInterval) when the app stops or if a new KNXInterfaceManager instance is created. This can leave multiple discovery loops running and keep resources alive longer than intended. Consider adding a
destroy()/onUninit-style cleanup that clearsthis.findDevicesInterval(and have the app call it on shutdown/reload).