@ircam/comote-helpers 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +28 -0
- package/README.md +157 -0
- package/package.json +45 -0
- package/qrcode.js +101 -0
- package/server.js +265 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
Copyright (c) 2015 IRCAM, Paris, France
|
|
2
|
+
All rights reserved.
|
|
3
|
+
|
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
|
5
|
+
modification, are permitted provided that the following conditions are met:
|
|
6
|
+
|
|
7
|
+
1. Redistributions of source code must retain the above copyright notice,
|
|
8
|
+
this list of conditions and the following disclaimer.
|
|
9
|
+
|
|
10
|
+
2. Redistributions in binary form must reproduce the above copyright
|
|
11
|
+
notice, this list of conditions and the following disclaimer in the
|
|
12
|
+
documentation and/or other materials provided with the distribution.
|
|
13
|
+
|
|
14
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
15
|
+
contributors may be used to endorse or promote products derived from
|
|
16
|
+
this software without specific prior written permission.
|
|
17
|
+
|
|
18
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
19
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
20
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
21
|
+
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
22
|
+
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
23
|
+
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
24
|
+
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
25
|
+
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
26
|
+
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
27
|
+
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
28
|
+
POSSIBILITY OF SUCH DAMAGE.
|
package/README.md
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# `@ircam/comote-helpers`
|
|
2
|
+
|
|
3
|
+
> Javascript and Max/MSP utilities to create applications compatible with iPhone
|
|
4
|
+
> and Android `CoMo.te` application.
|
|
5
|
+
|
|
6
|
+
## Table of Contents
|
|
7
|
+
|
|
8
|
+
<!-- toc -->
|
|
9
|
+
|
|
10
|
+
- [Install](#install)
|
|
11
|
+
- [API](#api)
|
|
12
|
+
* [Classes](#classes)
|
|
13
|
+
* [Functions](#functions)
|
|
14
|
+
* [Typedefs](#typedefs)
|
|
15
|
+
* [getWifiInfos() ⇒ WiFiInfos \| null](#getwifiinfos-%E2%87%92-wifiinfos--null)
|
|
16
|
+
* [rawLink()](#rawlink)
|
|
17
|
+
* [terminal(config)](#terminalconfig)
|
|
18
|
+
* [dataURL(config)](#dataurlconfig)
|
|
19
|
+
* [WifiInfos : Object](#wifiinfos--object)
|
|
20
|
+
* [CoMoteConfig : Object](#comoteconfig--object)
|
|
21
|
+
* [CoMoteTarget : Object](#comotetarget--object)
|
|
22
|
+
- [License](#license)
|
|
23
|
+
|
|
24
|
+
<!-- tocstop -->
|
|
25
|
+
|
|
26
|
+
## Install
|
|
27
|
+
|
|
28
|
+
```sh
|
|
29
|
+
npm install --save @ircam/comote-helpers
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## JS API
|
|
33
|
+
|
|
34
|
+
<!-- api -->
|
|
35
|
+
|
|
36
|
+
### Classes
|
|
37
|
+
|
|
38
|
+
<dl>
|
|
39
|
+
<dt><a href="#Server">Server</a></dt>
|
|
40
|
+
<dd><p>Launch WebSocket and/or OSC server according to given <code>CoMoteConfig</code> object</p>
|
|
41
|
+
</dd>
|
|
42
|
+
</dl>
|
|
43
|
+
|
|
44
|
+
### Functions
|
|
45
|
+
|
|
46
|
+
<dl>
|
|
47
|
+
<dt><a href="#getWifiInfos">getWifiInfos()</a> ⇒ <code>WiFiInfos</code> | <code>null</code></dt>
|
|
48
|
+
<dd><p>Retrieve the SSID and related IP of the first WiFi connection found, return
|
|
49
|
+
<code>null</code> if no WiFi connection found.</p>
|
|
50
|
+
</dd>
|
|
51
|
+
<dt><a href="#rawLink">rawLink()</a></dt>
|
|
52
|
+
<dd><p>Return the link to be encoded in the QRCode accroding to given <code>CoMoteConfig</code></p>
|
|
53
|
+
</dd>
|
|
54
|
+
<dt><a href="#terminal">terminal(config)</a></dt>
|
|
55
|
+
<dd><p>Create a qrcode to be logged in terminal according to given `CoMoteConfig``</p>
|
|
56
|
+
</dd>
|
|
57
|
+
<dt><a href="#dataURL">dataURL(config)</a></dt>
|
|
58
|
+
<dd><p>Create a qrcode to be used as in Image source according to given `CoMoteConfig``</p>
|
|
59
|
+
</dd>
|
|
60
|
+
</dl>
|
|
61
|
+
|
|
62
|
+
### Typedefs
|
|
63
|
+
|
|
64
|
+
<dl>
|
|
65
|
+
<dt><a href="#WifiInfos">WifiInfos</a> : <code>Object</code></dt>
|
|
66
|
+
<dd></dd>
|
|
67
|
+
<dt><a href="#CoMoteConfig">CoMoteConfig</a> : <code>Object</code></dt>
|
|
68
|
+
<dd></dd>
|
|
69
|
+
<dt><a href="#CoMoteTarget">CoMoteTarget</a> : <code>Object</code></dt>
|
|
70
|
+
<dd></dd>
|
|
71
|
+
</dl>
|
|
72
|
+
|
|
73
|
+
<a name="getWifiInfos"></a>
|
|
74
|
+
|
|
75
|
+
### getWifiInfos() ⇒ <code>WiFiInfos</code> \| <code>null</code>
|
|
76
|
+
Retrieve the SSID and related IP of the first WiFi connection found, return
|
|
77
|
+
`null` if no WiFi connection found.
|
|
78
|
+
|
|
79
|
+
**Kind**: global function
|
|
80
|
+
<a name="rawLink"></a>
|
|
81
|
+
|
|
82
|
+
### rawLink()
|
|
83
|
+
Return the link to be encoded in the QRCode accroding to given `CoMoteConfig`
|
|
84
|
+
|
|
85
|
+
**Kind**: global function
|
|
86
|
+
<a name="terminal"></a>
|
|
87
|
+
|
|
88
|
+
### terminal(config)
|
|
89
|
+
Create a qrcode to be logged in terminal according to given `CoMoteConfig``
|
|
90
|
+
|
|
91
|
+
**Kind**: global function
|
|
92
|
+
|
|
93
|
+
| Param | Type |
|
|
94
|
+
| --- | --- |
|
|
95
|
+
| config | [<code>CoMoteConfig</code>](#CoMoteConfig) |
|
|
96
|
+
|
|
97
|
+
**Example**
|
|
98
|
+
```js
|
|
99
|
+
console(CoMoteQRCode.terminal(config));
|
|
100
|
+
```
|
|
101
|
+
<a name="dataURL"></a>
|
|
102
|
+
|
|
103
|
+
### dataURL(config)
|
|
104
|
+
Create a qrcode to be used as in Image source according to given `CoMoteConfig``
|
|
105
|
+
|
|
106
|
+
**Kind**: global function
|
|
107
|
+
|
|
108
|
+
| Param | Type |
|
|
109
|
+
| --- | --- |
|
|
110
|
+
| config | [<code>CoMoteConfig</code>](#CoMoteConfig) |
|
|
111
|
+
|
|
112
|
+
**Example**
|
|
113
|
+
```js
|
|
114
|
+
<img src="${CoMoteQRCode.dataURL(config))}" />
|
|
115
|
+
```
|
|
116
|
+
<a name="WifiInfos"></a>
|
|
117
|
+
|
|
118
|
+
### WifiInfos : <code>Object</code>
|
|
119
|
+
**Kind**: global typedef
|
|
120
|
+
**Properties**
|
|
121
|
+
|
|
122
|
+
| Name | Type | Description |
|
|
123
|
+
| --- | --- | --- |
|
|
124
|
+
| ssid | <code>number</code> | SSID of the WiFi connection |
|
|
125
|
+
| ip | <code>number</code> | Related IP (IPV4) |
|
|
126
|
+
|
|
127
|
+
<a name="CoMoteConfig"></a>
|
|
128
|
+
|
|
129
|
+
### CoMoteConfig : <code>Object</code>
|
|
130
|
+
**Kind**: global typedef
|
|
131
|
+
**Properties**
|
|
132
|
+
|
|
133
|
+
| Name | Type | Description |
|
|
134
|
+
| --- | --- | --- |
|
|
135
|
+
| id | <code>String</code> | id of the client CoMo.te |
|
|
136
|
+
| interval | <code>Number</code> | period in ms of the sensors for the client CoMo.te |
|
|
137
|
+
| osc | [<code>CoMoteTarget</code>](#CoMoteTarget) | OSC configuration |
|
|
138
|
+
| ws | [<code>CoMoteTarget</code>](#CoMoteTarget) | WebSocket configuration |
|
|
139
|
+
|
|
140
|
+
<a name="CoMoteTarget"></a>
|
|
141
|
+
|
|
142
|
+
### CoMoteTarget : <code>Object</code>
|
|
143
|
+
**Kind**: global typedef
|
|
144
|
+
**Properties**
|
|
145
|
+
|
|
146
|
+
| Name | Type | Description |
|
|
147
|
+
| --- | --- | --- |
|
|
148
|
+
| hostname | <code>String</code> | hostname or ip of the WebSocket or OSC server |
|
|
149
|
+
| port | <code>Number</code> | listening port of the of the WebSocket or OSC server |
|
|
150
|
+
| autostart | <code>Boolean</code> | enable streaming on CoMo.te application |
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
<!-- apistop -->
|
|
154
|
+
|
|
155
|
+
## License
|
|
156
|
+
|
|
157
|
+
BSD-3-Clause
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ircam/comote-helpers",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "Server component & utilities for the CoMo.te application",
|
|
5
|
+
"authors": [
|
|
6
|
+
"Benjamin.Matuszewski@ircam.fr",
|
|
7
|
+
"Jean-Philippe.Lambert@ircam.fr"
|
|
8
|
+
],
|
|
9
|
+
"license": "BSD-3-Clause",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://github.com/ircam-ismm/comote-helpers"
|
|
13
|
+
},
|
|
14
|
+
"publishConfig": {
|
|
15
|
+
"access": "public"
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"api": "jsdoc-to-readme --src src/server.js src/qrcode.js",
|
|
19
|
+
"build": "npm run clean && babel src --out-dir .",
|
|
20
|
+
"clean": "rm -f server.js qrcode.js",
|
|
21
|
+
"dev": "npm run build && chokidar src -c \"npm run build\"",
|
|
22
|
+
"doc": "npm run api && npm run toc",
|
|
23
|
+
"prepublishOnly": "npm run build",
|
|
24
|
+
"toc": "markdown-toc -i README.md --maxdepth 3"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"assign-deep": "^1.0.1",
|
|
28
|
+
"clone-deep": "^4.0.1",
|
|
29
|
+
"debug": "^4.3.1",
|
|
30
|
+
"node-osc": "^7.0.0",
|
|
31
|
+
"qrcode": "^1.5.0",
|
|
32
|
+
"systeminformation": "^5.11.15",
|
|
33
|
+
"utf-8-validate": "^5.0.9",
|
|
34
|
+
"ws": "^8.6.0"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@babel/cli": "^7.4.4",
|
|
38
|
+
"@babel/core": "^7.4.5",
|
|
39
|
+
"@babel/preset-env": "^7.14.7",
|
|
40
|
+
"chokidar": "^3.0.1",
|
|
41
|
+
"chokidar-cli": "^2.1.0",
|
|
42
|
+
"jsdoc-to-readme": "^1.0.2",
|
|
43
|
+
"markdown-toc": "^1.2.0"
|
|
44
|
+
}
|
|
45
|
+
}
|
package/qrcode.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.dataURL = dataURL;
|
|
7
|
+
exports.rawLink = rawLink;
|
|
8
|
+
exports.terminal = terminal;
|
|
9
|
+
|
|
10
|
+
var _qrcode = _interopRequireDefault(require("qrcode"));
|
|
11
|
+
|
|
12
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
13
|
+
|
|
14
|
+
function formatConfigToLink(config) {
|
|
15
|
+
let link = `comote://settings?`;
|
|
16
|
+
const query = [];
|
|
17
|
+
|
|
18
|
+
if (Number.isFinite(config.id) && config.id >= 0) {
|
|
19
|
+
query.push(`id=${config.id}`);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (Number.isFinite(config.interval) && config.interval > 0) {
|
|
23
|
+
query.push(`interval=${config.interval}`);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (config.ws) {
|
|
27
|
+
const {
|
|
28
|
+
hostname,
|
|
29
|
+
port
|
|
30
|
+
} = config.ws;
|
|
31
|
+
|
|
32
|
+
if (!hostname || !Number.isInteger(port)) {
|
|
33
|
+
throw new Error(`Invalid WebSocket config: ${config.ws}`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
query.push(`ws-url=ws://${hostname}:${port}`);
|
|
37
|
+
|
|
38
|
+
if (config.ws.autostart === true) {
|
|
39
|
+
query.push(`ws-enable=1`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (config.osc) {
|
|
44
|
+
const {
|
|
45
|
+
hostname,
|
|
46
|
+
port
|
|
47
|
+
} = config.osc;
|
|
48
|
+
|
|
49
|
+
if (!hostname || !Number.isInteger(port)) {
|
|
50
|
+
throw new Error(`Invalid WebSocket config: ${config.osc}`);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
query.push(`osc-url=udp://${hostname}:${port}`);
|
|
54
|
+
|
|
55
|
+
if (config.osc.autostart === true) {
|
|
56
|
+
query.push(`osc-enable=1`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
link += query.join('&');
|
|
61
|
+
return link;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Return the link to be encoded in the QRCode accroding to given `CoMoteConfig`
|
|
65
|
+
*/
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
function rawLink(config) {
|
|
69
|
+
return formatConfigToLink(config);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Create a qrcode to be logged in terminal according to given `CoMoteConfig``
|
|
73
|
+
*
|
|
74
|
+
* @param {CoMoteConfig} config
|
|
75
|
+
* @example
|
|
76
|
+
* console(await CoMoteQRCode.terminal(config));
|
|
77
|
+
*/
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
async function terminal(config) {
|
|
81
|
+
const link = formatConfigToLink(config);
|
|
82
|
+
return await _qrcode.default.toString(link, {
|
|
83
|
+
type: 'terminal',
|
|
84
|
+
small: true
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Create a qrcode to be used as in Image source according to given `CoMoteConfig``
|
|
89
|
+
*
|
|
90
|
+
* @param {CoMoteConfig} config
|
|
91
|
+
* @example
|
|
92
|
+
* const qrCode = await CoMoteQRCode.dataURL(config));
|
|
93
|
+
*
|
|
94
|
+
* <img src="${qrCode}" />
|
|
95
|
+
*/
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
async function dataURL(config) {
|
|
99
|
+
const link = formatConfigToLink(config);
|
|
100
|
+
return await await _qrcode.default.toDataURL(link);
|
|
101
|
+
}
|
package/server.js
ADDED
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.Server = void 0;
|
|
7
|
+
exports.getWifiInfos = getWifiInfos;
|
|
8
|
+
|
|
9
|
+
var _systeminformation = _interopRequireDefault(require("systeminformation"));
|
|
10
|
+
|
|
11
|
+
var _ws = _interopRequireDefault(require("ws"));
|
|
12
|
+
|
|
13
|
+
var _utf8Validate = _interopRequireDefault(require("utf-8-validate"));
|
|
14
|
+
|
|
15
|
+
var _nodeOsc = require("node-osc");
|
|
16
|
+
|
|
17
|
+
var _cloneDeep = _interopRequireDefault(require("clone-deep"));
|
|
18
|
+
|
|
19
|
+
var _assignDeep = _interopRequireDefault(require("assign-deep"));
|
|
20
|
+
|
|
21
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @typedef {Object} WifiInfos
|
|
25
|
+
* @property {number} ssid - SSID of the WiFi connection
|
|
26
|
+
* @property {number} ip - Related IP (IPV4)
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @typedef {Object} CoMoteConfig
|
|
31
|
+
* @property {String} id - id of the client CoMo.te
|
|
32
|
+
* @property {Number} interval - period in ms of the sensors for the client CoMo.te
|
|
33
|
+
* @property {CoMoteTarget} osc - OSC configuration
|
|
34
|
+
* @property {CoMoteTarget} ws - WebSocket configuration
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @typedef {Object} CoMoteTarget
|
|
39
|
+
* @property {String} hostname - hostname or ip of the WebSocket or OSC server
|
|
40
|
+
* @property {Number} port - listening port of the of the WebSocket or OSC server
|
|
41
|
+
* @property {Boolean} autostart - enable streaming on CoMo.te application
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Retrieve the SSID and related IP of the first WiFi connection found, return
|
|
46
|
+
* `null` if no WiFi connection found.
|
|
47
|
+
*
|
|
48
|
+
* @async
|
|
49
|
+
* @return {WiFiInfos|null}
|
|
50
|
+
*/
|
|
51
|
+
async function getWifiInfos() {
|
|
52
|
+
// find first wifi connection
|
|
53
|
+
const wifiConnections = await _systeminformation.default.wifiConnections();
|
|
54
|
+
const conn = wifiConnections[0];
|
|
55
|
+
|
|
56
|
+
if (!conn) {
|
|
57
|
+
return null;
|
|
58
|
+
} // find related interface
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
const interfaces = await _systeminformation.default.networkInterfaces();
|
|
62
|
+
const int = interfaces.find(int => int.iface === conn.iface);
|
|
63
|
+
return {
|
|
64
|
+
ssid: conn.ssid,
|
|
65
|
+
ip: int.ip4
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Launch WebSocket and/or OSC server according to given `CoMoteConfig` object
|
|
70
|
+
*
|
|
71
|
+
* @param {CoMoteConfig} config - CoMote configuration
|
|
72
|
+
* @param {Object} options - options
|
|
73
|
+
* @param {Object} [options.verbose=false] - logs debug informations
|
|
74
|
+
*/
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class Server {
|
|
78
|
+
constructor(config, options) {
|
|
79
|
+
/**
|
|
80
|
+
* Configuration of the CoMote server
|
|
81
|
+
*/
|
|
82
|
+
this.config = (0, _cloneDeep.default)((0, _assignDeep.default)({
|
|
83
|
+
id: null,
|
|
84
|
+
interval: null,
|
|
85
|
+
osc: null,
|
|
86
|
+
ws: null,
|
|
87
|
+
verbose: false
|
|
88
|
+
}, config));
|
|
89
|
+
this._verbose = !!options.verbose;
|
|
90
|
+
|
|
91
|
+
if (this._verbose) {
|
|
92
|
+
console.log('+ CoMo.te config:');
|
|
93
|
+
console.log(this.config, '\n');
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
this._websocketServer = null;
|
|
97
|
+
this._oscServer = null;
|
|
98
|
+
this._wsListeners = new Set();
|
|
99
|
+
this._oscListeners = new Set();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
async start() {
|
|
103
|
+
let wsPromise = true;
|
|
104
|
+
let oscPromise = true;
|
|
105
|
+
|
|
106
|
+
if (this.config.ws !== null) {
|
|
107
|
+
const {
|
|
108
|
+
hostname,
|
|
109
|
+
port
|
|
110
|
+
} = this.config.ws;
|
|
111
|
+
|
|
112
|
+
if (!Number.isInteger(port)) {
|
|
113
|
+
throw new Error(`Invalid port "${port}" for WebSocket server`);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (this._verbose) {
|
|
117
|
+
console.log(`> CoMo.te: Launching WebSocket server on port: ${port}`);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
this._websocketServer = new _ws.default.Server({
|
|
121
|
+
port
|
|
122
|
+
});
|
|
123
|
+
const sockets = new Map();
|
|
124
|
+
|
|
125
|
+
this._websocketServer.on('connection', (socket, request) => {
|
|
126
|
+
// const ip = request.socket.remoteAddress;
|
|
127
|
+
socket.on('message', (data, isBinary) => {
|
|
128
|
+
if (isBinary) {// @todo
|
|
129
|
+
} else {
|
|
130
|
+
if ((0, _utf8Validate.default)(data)) {
|
|
131
|
+
// do we really need this check?
|
|
132
|
+
data = JSON.parse(data);
|
|
133
|
+
|
|
134
|
+
if (this._verbose) {
|
|
135
|
+
console.log(`> CoMo.te: new WebSocket message`, data);
|
|
136
|
+
} // console.log(data);
|
|
137
|
+
// console.log(this._wsListeners.size);
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
this._wsListeners.forEach(listener => listener(data));
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}); // When a socket closes, or disconnects, remove it from the array.
|
|
144
|
+
|
|
145
|
+
socket.on('close', (code, data) => {
|
|
146
|
+
if (this._verbose) {
|
|
147
|
+
console.log('> CoMo.te: closed socket connection');
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
wsPromise = new Promise((resolve, reject) => {
|
|
153
|
+
this._websocketServer.on('listening', () => {
|
|
154
|
+
if (this._verbose) {
|
|
155
|
+
console.log(`> CoMo.te: WebSocket server listening`);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
resolve();
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
this._websocketServer.on('error', err => {
|
|
162
|
+
console.log(`> CoMo.te: WebSocket server error`, err);
|
|
163
|
+
reject(err);
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (this.config.osc !== null) {
|
|
169
|
+
const {
|
|
170
|
+
hostname,
|
|
171
|
+
port
|
|
172
|
+
} = this.config.osc;
|
|
173
|
+
|
|
174
|
+
if (!Number.isInteger(port)) {
|
|
175
|
+
throw new Error(`Invalid port "${port}" for OSC server`);
|
|
176
|
+
} // fallback to broadcast
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
if (!hostname) {
|
|
180
|
+
hostname = '0.0.0.0';
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (this._verbose) {
|
|
184
|
+
console.log(`> CoMo.te: Launching OSC server udp://${hostname}:${port}`);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
oscPromise = new Promise((resolve, reject) => {
|
|
188
|
+
this._oscServer = new _nodeOsc.Server(this.config.osc.port, hostname, err => {
|
|
189
|
+
if (err) {
|
|
190
|
+
console.log(`> CoMo.te: OSC server error`, err);
|
|
191
|
+
reject();
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (this._verbose) {
|
|
196
|
+
console.log(`> CoMo.te: OSC server listening`);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
resolve();
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
this._oscServer.on('message', data => {
|
|
203
|
+
let address = data.shift();
|
|
204
|
+
|
|
205
|
+
if (this._verbose) {
|
|
206
|
+
console.log(`> CoMo.te: new OSC message "${address}":`, data);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
this._oscListeners.forEach(callback => callback(address, data));
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return Promise.all([wsPromise, oscPromise]);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
async stop() {
|
|
218
|
+
if (this._websocketServer) {
|
|
219
|
+
this._websocketServer.close();
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
if (this._oscServer) {
|
|
223
|
+
this._oscServer.close();
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Add a listener for incomming WebSocket message
|
|
228
|
+
*/
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
addWsListener(callback) {
|
|
232
|
+
this._wsListeners.add(callback);
|
|
233
|
+
|
|
234
|
+
return () => this._wsListeners.delete(callback);
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Remove WebSocket listener
|
|
238
|
+
*/
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
removeWsListener(callback) {
|
|
242
|
+
this._wsListeners.delete(callback);
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Add a listener for incomming OSC message
|
|
246
|
+
*/
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
addOscListener(callback) {
|
|
250
|
+
this._oscListeners.add(callback);
|
|
251
|
+
|
|
252
|
+
return () => this._oscListeners.delete(callback);
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Remove OSC listener
|
|
256
|
+
*/
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
removeOscListener(callback) {
|
|
260
|
+
this._oscListeners.delete(callback);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
exports.Server = Server;
|