Skip to content

Commit

Permalink
Improve discovery example to support IPv6.
Browse files Browse the repository at this point in the history
  • Loading branch information
danielwippermann committed Jan 20, 2024
1 parent 07eed95 commit 4979d2a
Showing 1 changed file with 86 additions and 35 deletions.
121 changes: 86 additions & 35 deletions examples/discovery/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
/*! resol-vbus | Copyright (c) 2013-present, Daniel Wippermann | MIT license */

const os = require('os');

const {
TcpDataSourceProvider,
} = require('../resol-vbus');
Expand All @@ -9,79 +11,128 @@ const {
const knownDataSources = new Map();


const fetchCallback = async (address) => {
async function getOrFetchInformation(key, interfaceName, address, discoveredAddress) {
let result;
if (knownDataSources.has(address)) {
result = knownDataSources.get(address);
if (knownDataSources.has(key)) {
result = knownDataSources.get(key);
} else {
// console.log('QUERY: ', address);
result = TcpDataSourceProvider.fetchDeviceInformation(address);
result = result.then((result) => {
// console.log('QUERY SUCCESS: ', address);
return result;
}, (reason) => {
console.log('QUERY FAILED: ', address);
return {};
});
if (address.family === 'IPv4') {
result = await TcpDataSourceProvider.fetchDeviceInformation({
hostname: discoveredAddress,
family: 4,
});
} else if (address.family === 'IPv6') {
result = await TcpDataSourceProvider.fetchDeviceInformation({
hostname: discoveredAddress,
localAdress: `${address.address}%${interfaceName}`,
family: 6,
});
}

knownDataSources.set(key, result);
}
return result;
};
}

async function discover() {
const interfaceMap = os.networkInterfaces();

const interfaceNames = Object.getOwnPropertyNames(interfaceMap);

const knownKeySet = new Set(knownDataSources.keys());
const fetchedKeySet = new Set();

const discover = async () => {
const devices = await TcpDataSourceProvider.discoverDevices({
// ipv6: true,
// broadcastInterface: 'en0',
const commonDiscoveryOptions = {
broadcastPort: 7053,
tries: 3,
timeout: 500,
fetchCallback,
});
};

const promises = [];
for (const interfaceName of interfaceNames) {
const addresses = interfaceMap [interfaceName];

let preferredIPv6Address = null;
for (const address of addresses) {
if (address.family === 'IPv4') {
const promise = TcpDataSourceProvider.discoverDevices({
localAddress: address.address,
netmask: address.netmask,
...commonDiscoveryOptions,
fetchCallback(discoveredAddress) {
const key = discoveredAddress;
fetchedKeySet.add(key);
return getOrFetchInformation(key, interfaceName, address, discoveredAddress);
},
});

promises.push(promise);
} else if (address.family === 'IPv6') {
if ((preferredIPv6Address == null) || (preferredIPv6Address.scopeid < address.scopeid)) {
preferredIPv6Address = address;
}
}
}

const deviceById = devices.reduce((memo, device) => {
const id = device.__address__;
memo.set(id, device);
return memo;
}, new Map());
if (preferredIPv6Address) {
const promise = TcpDataSourceProvider.discoverDevices({
family: 'IPv6',
localAddress: preferredIPv6Address.address,
broadcastInterface: interfaceName,
...commonDiscoveryOptions,
fetchCallback(discoveredAddress) {
const key = `${discoveredAddress}%${interfaceName}`;
fetchedKeySet.add(key);
return getOrFetchInformation(key, interfaceName, preferredIPv6Address, discoveredAddress);
},
});

promises.push(promise);
}
}

const addedDevices = devices.reduce((memo, device) => {
const id = device.__address__;
if (!knownDataSources.has(id)) {
await Promise.all(promises);

const addedDevices = Array.from(fetchedKeySet.values()).reduce((memo, key) => {
if (!knownKeySet.has(key)) {
const device = knownDataSources.get(key);
memo.push(device);
}
return memo;
}, []);

const removedDevices = [...knownDataSources.keys()].reduce((memo, id) => {
if (!deviceById.has(id)) {
memo.push(knownDataSources.get(id));
const removedDevices = Array.from(knownKeySet.values()).reduce((memo, key) => {
if (!fetchedKeySet.has(key)) {
const device = knownDataSources.get(key);
knownDataSources.delete(key);
memo.push(device);
}
return memo;
}, []);

for (const device of removedDevices) {
const id = device.__address__;
knownDataSources.delete(id);
console.log('REMOVED: ', id, device.name);
}

for (const device of addedDevices) {
const id = device.__address__;
knownDataSources.set(id, device);
console.log('ADDED: ', id, device.name);
}
};
}



async function main() {
const interval = 10000;

const main = async () => {
while (true) {
console.log('------', new Date(), '------');

await discover();

await new Promise((resolve) => {
setTimeout(resolve, 10000);
setTimeout(resolve, interval - (Date.now() % interval));
});
}
};
Expand Down

0 comments on commit 4979d2a

Please sign in to comment.