@elgato-stream-deck/tcp
Version:
An npm module for interfacing with select Elgato Stream Deck devices in node over tcp
106 lines • 3.92 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.StreamDeckTcpDiscoveryService = void 0;
const bonjour_service_1 = require("@julusian/bonjour-service");
const events_1 = require("events");
const constants_js_1 = require("./constants.js");
const core_1 = require("@elgato-stream-deck/core");
const core_2 = require("@elgato-stream-deck/core");
function convertService(service) {
if (!service.addresses || service.addresses.length === 0)
return null;
const dt = Number(service.txt.dt);
if (isNaN(dt))
return null;
if (dt === 215) {
// This should be a Stream Deck Network Dock
// The implementation isn't ideal, but it works well enough and avoids a breaking change to the types
return {
address: service.addresses[0],
port: service.port,
name: service.name,
vendorId: core_2.VENDOR_ID,
productId: 0xffff, // This doesn't have a product id, but we need to set it to something
serialNumber: service.txt.sn,
modelType: core_1.DeviceModelType.NETWORK_DOCK,
modelId: core_1.DeviceModelId.NETWORK_DOCK,
modelName: core_1.MODEL_NAMES[core_1.DeviceModelId.NETWORK_DOCK],
isPrimary: true,
};
}
// Get and parse the vendor and product id
const vendorId = Number(service.txt.vid);
const productId = Number(service.txt.pid);
if (isNaN(vendorId) || isNaN(productId))
return null;
// Find the corresponding model
const model = core_2.DEVICE_MODELS.find((model) => core_2.VENDOR_ID === vendorId && model.productIds.includes(productId));
if (!model)
return null;
return {
address: service.addresses[0],
port: service.port,
name: service.name,
vendorId,
productId,
serialNumber: service.txt.sn,
modelType: model.type,
modelId: model.id,
modelName: model.productName,
isPrimary: model.hasNativeTcp,
};
}
class StreamDeckTcpDiscoveryService extends events_1.EventEmitter {
#server;
#browser;
#queryInterval;
constructor(options) {
super();
this.#server = new bonjour_service_1.Bonjour();
this.#browser = this.#server.find({
type: 'elg',
protocol: 'tcp',
});
this.#browser.on('up', (service) => this.#emitUp(service));
this.#browser.on('down', (service) => this.#emitDown(service));
this.#browser.on('srv-update', (newService, existingService) => {
this.#emitDown(existingService);
this.#emitUp(newService);
});
const queryInterval = options?.queryInterval ?? constants_js_1.DEFAULT_MDNS_QUERY_INTERVAL;
if (queryInterval >= 0) {
this.#queryInterval = setInterval(() => this.query(), queryInterval);
}
}
get knownStreamDecks() {
return this.#browser.services.map(convertService).filter((svc) => !!svc);
}
#emitDown(service) {
const serviceDefinition = convertService(service);
if (!serviceDefinition)
return;
this.emit('down', serviceDefinition);
}
#emitUp(service) {
const serviceDefinition = convertService(service);
if (!serviceDefinition)
return;
this.emit('up', serviceDefinition);
}
/**
* Broadcast the query to the network
*/
query() {
// Tell the browser to resend the query
this.#browser.update();
// Tell the browser to expire any services that haven't been seen in a while
this.#browser.expire();
}
destroy() {
if (this.#queryInterval)
clearInterval(this.#queryInterval);
this.#server.destroy();
}
}
exports.StreamDeckTcpDiscoveryService = StreamDeckTcpDiscoveryService;
//# sourceMappingURL=discoveryService.js.map