UNPKG

6.21 kBJavaScriptView Raw
1"use strict";
2var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3 function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4 return new (P || (P = Promise))(function (resolve, reject) {
5 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7 function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8 step((generator = generator.apply(thisArg, _arguments || [])).next());
9 });
10};
11Object.defineProperty(exports, "__esModule", { value: true });
12const expect = require("@fantasticfiasco/expect");
13const events = require("events");
14const logging_1 = require("./logging");
15const network_interfaces_1 = require("./network-interfaces");
16const options_1 = require("./options");
17const root_descriptions_1 = require("./root-descriptions");
18const sockets_1 = require("./sockets");
19/**
20 * Class responsible for discovering Axis cameras on the network.
21 */
22class Discovery {
23 /**
24 * Initializes a new instance of the class.
25 * @param options The SSDP discovery options.
26 */
27 constructor(options) {
28 this.eventEmitter = new events.EventEmitter();
29 this.options = options || {};
30 }
31 /**
32 * Start listen for device advertisements on all network interface
33 * addresses.
34 */
35 start() {
36 return __awaiter(this, void 0, void 0, function* () {
37 expect.toNotExist(this.sockets, 'Discovery has already been started');
38 logging_1.log('Discovery#start');
39 yield this.setup();
40 });
41 }
42 /**
43 * Stop listening for device advertisements.
44 */
45 stop() {
46 return __awaiter(this, void 0, void 0, function* () {
47 expect.toExist(this.sockets, 'Discovery has not been started');
48 logging_1.log('Discovery#stop');
49 yield this.teardown();
50 });
51 }
52 /**
53 * Triggers a new search for devices on the network.
54 */
55 search() {
56 return __awaiter(this, void 0, void 0, function* () {
57 expect.toExist(this.sockets, 'Discovery has not been started');
58 logging_1.log('Discovery#search');
59 for (const socket of this.sockets) {
60 if (socket instanceof sockets_1.MSearchSocket) {
61 yield socket.search();
62 }
63 }
64 });
65 }
66 /**
67 * Register a callback that is invoked when a device is found on the
68 * network.
69 */
70 onHello(callback) {
71 this.eventEmitter.on('hello', (device) => callback(device));
72 }
73 /**
74 * Register a callback that is invoked when a device intentionally is
75 * disconnecting from the network.
76 */
77 onGoodbye(callback) {
78 this.eventEmitter.on('goodbye', (device) => callback(device));
79 }
80 setup() {
81 return __awaiter(this, void 0, void 0, function* () {
82 this.sockets = [];
83 const addresses = network_interfaces_1.getIPv4Addresses();
84 logging_1.log('Discovery#setup - interface addresses: %o', addresses);
85 // Passive SSDP
86 yield this.setupSocket(new sockets_1.NotifySocket(addresses));
87 // Active SSDP
88 for (const address of addresses) {
89 yield this.setupSocket(new sockets_1.MSearchSocket(address));
90 }
91 });
92 }
93 setupSocket(socket) {
94 return __awaiter(this, void 0, void 0, function* () {
95 this.sockets.push(socket);
96 socket.on('hello', (message) => this.onHelloMessage(message));
97 socket.on('goodbye', (message) => this.onGoodbyeMessage(message));
98 yield socket.start();
99 });
100 }
101 teardown() {
102 return __awaiter(this, void 0, void 0, function* () {
103 for (const socket of this.sockets) {
104 this.teardownSocket(socket);
105 }
106 this.sockets = undefined;
107 });
108 }
109 teardownSocket(socket) {
110 return __awaiter(this, void 0, void 0, function* () {
111 socket.removeAllListeners('hello');
112 socket.removeAllListeners('goodbye');
113 yield socket.stop();
114 });
115 }
116 onHelloMessage(message) {
117 logging_1.log('Discovery#onHelloMessage - %s', message.remoteAddress);
118 const device = sockets_1.mapFromMessage(message);
119 if (device) {
120 // Emit initial hello
121 this.eventEmitter.emit('hello', device);
122 // Request root description
123 this.requestRootDescription(message.remoteAddress, message.location);
124 }
125 else {
126 logging_1.log('Discovery#onHelloMessage - ignore %s since mapping was unsuccessful', message.remoteAddress);
127 }
128 }
129 onGoodbyeMessage(message) {
130 logging_1.log('Discovery#onGoodbyeMessage - %s', message.remoteAddress);
131 const device = sockets_1.mapFromMessage(message);
132 if (device) {
133 this.eventEmitter.emit('goodbye', device);
134 }
135 else {
136 logging_1.log('Discovery#onGoodbyeMessage - ignore %s since mapping was unsuccessful', message.remoteAddress);
137 }
138 }
139 requestRootDescription(remoteAddress, location) {
140 return __awaiter(this, void 0, void 0, function* () {
141 try {
142 const httpClient = this.options.httpClient || new options_1.HttpClient();
143 const rootDescriptionRequest = new root_descriptions_1.RootDescriptionRequest(remoteAddress, location, httpClient);
144 const rootDescription = yield rootDescriptionRequest.send();
145 const device = root_descriptions_1.mapFromRootDescription(rootDescription);
146 if (device !== null) {
147 this.eventEmitter.emit('hello', device);
148 }
149 }
150 catch (error) {
151 logging_1.log('Discovery#requestRootDescription - %o', error);
152 }
153 });
154 }
155}
156exports.Discovery = Discovery;
157//# sourceMappingURL=Discovery.js.map
\No newline at end of file