node-red-contrib-antenna-genius 0.2.5-beta → 0.3.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/Utils.js +72 -55
- package/antenna-genius-activate-antenna.html +14 -13
- package/antenna-genius-activate-antenna.js +44 -17
- package/antenna-genius-antenna-status.html +29 -18
- package/antenna-genius-antenna-status.js +73 -27
- package/antenna-genius-band-labels.html +14 -12
- package/antenna-genius-band-labels.js +48 -16
- package/antenna-genius-server.html +35 -21
- package/antenna-genius-server.js +37 -26
- package/examples/Antenna Genius.json +229 -0
- package/examples/Antenna Genius.png +0 -0
- package/package.json +1 -1
- package/test/Utils.spec.js +141 -0
- package/test/antenna-genius-activate-antenna.spec.js +110 -72
- package/test/antenna-genius-antenna-status.spec.js +163 -106
- package/test/antenna-genius-band-labels.spec.js +137 -103
- package/test/antenna-genius-server.spec.js +51 -31
|
@@ -3,41 +3,56 @@ module.exports = (RED) => {
|
|
|
3
3
|
constructor(config) {
|
|
4
4
|
RED.nodes.createNode(this, config);
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
let node = this;
|
|
7
7
|
this.bandNameA = "";
|
|
8
8
|
this.bandNameB = "";
|
|
9
9
|
this.server = RED.nodes.getNode(config.server);
|
|
10
10
|
|
|
11
|
+
if(this.server == null) {
|
|
12
|
+
this.status({
|
|
13
|
+
fill: "red",
|
|
14
|
+
shape: "ring",
|
|
15
|
+
text: "disconnected",
|
|
16
|
+
});
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
|
|
11
20
|
this.server.updatesEventEmitter.on("connected", () => {
|
|
12
|
-
if(this.server.info.name) {
|
|
13
|
-
this.status({
|
|
21
|
+
if (this.server.info.name) {
|
|
22
|
+
this.status({
|
|
23
|
+
fill: "green",
|
|
24
|
+
shape: "dot",
|
|
25
|
+
text: this.server.info.name,
|
|
26
|
+
});
|
|
14
27
|
}
|
|
15
28
|
});
|
|
16
29
|
|
|
17
|
-
this.server.updatesEventEmitter.on(
|
|
18
|
-
this.status({
|
|
30
|
+
this.server.updatesEventEmitter.on("closed", () => {
|
|
31
|
+
this.status({
|
|
32
|
+
fill: "red",
|
|
33
|
+
shape: "ring",
|
|
34
|
+
text: "disconnected",
|
|
35
|
+
});
|
|
19
36
|
});
|
|
20
37
|
|
|
21
38
|
this.server.updatesEventEmitter.on("status", (forceUpdate) => {
|
|
22
39
|
let bandIndexA = this.server.status.portA_band;
|
|
23
40
|
let bandIndexB = this.server.status.portB_band;
|
|
24
41
|
|
|
25
|
-
if(bandIndexA === undefined || bandIndexB === undefined) {
|
|
42
|
+
if (bandIndexA === undefined || bandIndexB === undefined) {
|
|
26
43
|
return;
|
|
27
44
|
}
|
|
28
45
|
|
|
29
|
-
if(bandIndexA < 0 || bandIndexA >= this.server.bands.length)
|
|
30
|
-
{
|
|
46
|
+
if (bandIndexA < 0 || bandIndexA >= this.server.bands.length) {
|
|
31
47
|
return;
|
|
32
48
|
}
|
|
33
49
|
|
|
34
|
-
if(bandIndexB < 0 || bandIndexB >= this.server.bands.length)
|
|
35
|
-
{
|
|
50
|
+
if (bandIndexB < 0 || bandIndexB >= this.server.bands.length) {
|
|
36
51
|
return;
|
|
37
52
|
}
|
|
38
53
|
|
|
39
|
-
let bandNameA = this.server.bands[bandIndexA].
|
|
40
|
-
let bandNameB = this.server.bands[bandIndexB].
|
|
54
|
+
let bandNameA = this.server.bands[bandIndexA].name;
|
|
55
|
+
let bandNameB = this.server.bands[bandIndexB].name;
|
|
41
56
|
|
|
42
57
|
let changed = forceUpdate;
|
|
43
58
|
if (bandNameA !== this.bandNameA) {
|
|
@@ -49,13 +64,30 @@ module.exports = (RED) => {
|
|
|
49
64
|
this.bandNameB = bandNameB;
|
|
50
65
|
}
|
|
51
66
|
if (changed) {
|
|
52
|
-
node.send({
|
|
53
|
-
|
|
67
|
+
node.send({
|
|
68
|
+
payload: {
|
|
69
|
+
bandLabelA: bandNameA,
|
|
70
|
+
bandLabelB: bandNameB,
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
this.status({
|
|
74
|
+
fill: "green",
|
|
75
|
+
shape: "dot",
|
|
76
|
+
text:
|
|
77
|
+
this.server.info.name +
|
|
78
|
+
" - " +
|
|
79
|
+
bandNameA +
|
|
80
|
+
"/" +
|
|
81
|
+
bandNameB,
|
|
82
|
+
});
|
|
54
83
|
}
|
|
55
84
|
});
|
|
56
85
|
|
|
57
86
|
this.server.connect();
|
|
58
87
|
}
|
|
59
88
|
}
|
|
60
|
-
RED.nodes.registerType(
|
|
61
|
-
|
|
89
|
+
RED.nodes.registerType(
|
|
90
|
+
"antenna-genius-band-labels",
|
|
91
|
+
AntennaGeniusBandLabels
|
|
92
|
+
);
|
|
93
|
+
};
|
|
@@ -1,41 +1,55 @@
|
|
|
1
1
|
<script type="text/javascript">
|
|
2
|
-
RED.nodes.registerType(
|
|
3
|
-
category:
|
|
4
|
-
color:
|
|
2
|
+
RED.nodes.registerType("antenna-genius-server", {
|
|
3
|
+
category: "config",
|
|
4
|
+
color: "#FFF0F0",
|
|
5
5
|
defaults: {
|
|
6
|
-
host: {value:"localhost",required:true},
|
|
7
|
-
port: {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
host: { value: "localhost", required: true },
|
|
7
|
+
port: {
|
|
8
|
+
value: 9007,
|
|
9
|
+
required: true,
|
|
10
|
+
validate: RED.validators.number(),
|
|
11
|
+
},
|
|
12
|
+
disabledColor: { value: "Black", required: true },
|
|
13
|
+
activeColor: { value: "Green", required: true },
|
|
14
|
+
selectedColor: { value: "Blue", required: true },
|
|
15
|
+
autoConnect: { value: true },
|
|
12
16
|
},
|
|
13
|
-
label: function() {
|
|
17
|
+
label: function () {
|
|
14
18
|
return "antenna genius at " + this.host + ":" + this.port;
|
|
15
|
-
}
|
|
19
|
+
},
|
|
16
20
|
});
|
|
17
21
|
</script>
|
|
18
22
|
|
|
19
23
|
<script type="text/html" data-template-name="antenna-genius-server">
|
|
20
24
|
<div class="form-row">
|
|
21
|
-
<label for="node-config-input-host"
|
|
22
|
-
|
|
25
|
+
<label for="node-config-input-host"
|
|
26
|
+
><i class="fa fa-bookmark"></i> Host</label
|
|
27
|
+
>
|
|
28
|
+
<input type="text" id="node-config-input-host" />
|
|
23
29
|
</div>
|
|
24
30
|
<div class="form-row">
|
|
25
|
-
<label for="node-config-input-port"
|
|
26
|
-
|
|
31
|
+
<label for="node-config-input-port"
|
|
32
|
+
><i class="fa fa-bookmark"></i> Port</label
|
|
33
|
+
>
|
|
34
|
+
<input type="text" id="node-config-input-port" />
|
|
27
35
|
</div>
|
|
28
36
|
<div class="form-row">
|
|
29
|
-
<label for="node-config-input-disabledColor"
|
|
30
|
-
|
|
37
|
+
<label for="node-config-input-disabledColor"
|
|
38
|
+
><i class="fa fa-bookmark"></i> Disabled Background</label
|
|
39
|
+
>
|
|
40
|
+
<input type="text" id="node-config-input-disabledColor" />
|
|
31
41
|
</div>
|
|
32
42
|
<div class="form-row">
|
|
33
|
-
<label for="node-config-input-activeColor"
|
|
34
|
-
|
|
43
|
+
<label for="node-config-input-activeColor"
|
|
44
|
+
><i class="fa fa-bookmark"></i> Active Background</label
|
|
45
|
+
>
|
|
46
|
+
<input type="text" id="node-config-input-activeColor" />
|
|
35
47
|
</div>
|
|
36
48
|
<div class="form-row">
|
|
37
|
-
<label for="node-config-input-selectedColor"
|
|
38
|
-
|
|
49
|
+
<label for="node-config-input-selectedColor"
|
|
50
|
+
><i class="fa fa-bookmark"></i> Selected Background</label
|
|
51
|
+
>
|
|
52
|
+
<input type="text" id="node-config-input-selectedColor" />
|
|
39
53
|
</div>
|
|
40
54
|
</script>
|
|
41
55
|
|
package/antenna-genius-server.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
const Net = require(
|
|
2
|
-
const {PromiseSocket} = require("promise-socket");
|
|
3
|
-
const EventEmitter = require(
|
|
4
|
-
const Utils = require(
|
|
1
|
+
const Net = require("net");
|
|
2
|
+
const { PromiseSocket } = require("promise-socket");
|
|
3
|
+
const EventEmitter = require("events");
|
|
4
|
+
const Utils = require("./Utils");
|
|
5
5
|
|
|
6
6
|
class UpdatesEventEmitter extends EventEmitter {}
|
|
7
7
|
|
|
@@ -22,7 +22,7 @@ module.exports = (RED) => {
|
|
|
22
22
|
this.bands = [];
|
|
23
23
|
this.interval = null;
|
|
24
24
|
this.timer = null;
|
|
25
|
-
this.refresh =
|
|
25
|
+
this.refresh = -1;
|
|
26
26
|
|
|
27
27
|
this.updatesEventEmitter = new UpdatesEventEmitter();
|
|
28
28
|
this.updatesEventEmitter.setMaxListeners(0);
|
|
@@ -30,30 +30,34 @@ module.exports = (RED) => {
|
|
|
30
30
|
this.client = new Net.Socket();
|
|
31
31
|
this.connected = false;
|
|
32
32
|
|
|
33
|
-
this.client.on(
|
|
34
|
-
this.log(
|
|
33
|
+
this.client.on("close", () => {
|
|
34
|
+
this.log("TCP connection disconnected with the server.");
|
|
35
35
|
clearInterval(this.interval);
|
|
36
36
|
clearTimeout(this.timer);
|
|
37
37
|
|
|
38
|
-
if(this.updatesEventEmitter.listenerCount(
|
|
39
|
-
this.log(
|
|
38
|
+
if (this.updatesEventEmitter.listenerCount("closed") == 0) {
|
|
39
|
+
this.log(
|
|
40
|
+
"Stop retrying. No nodes are refering this connection anymore."
|
|
41
|
+
);
|
|
40
42
|
return;
|
|
41
43
|
}
|
|
42
44
|
|
|
43
|
-
if(this.autoConnect) {
|
|
44
|
-
this.log(
|
|
45
|
+
if (this.autoConnect) {
|
|
46
|
+
this.log(
|
|
47
|
+
"TCP connection failed with the server. Will try to reconnect in 5 seconds"
|
|
48
|
+
);
|
|
45
49
|
this.timer = setTimeout(() => {
|
|
46
|
-
this.log(
|
|
50
|
+
this.log("Reconnecting...");
|
|
47
51
|
this.connect();
|
|
48
52
|
}, 5000);
|
|
49
53
|
this.updatesEventEmitter.emit("closed");
|
|
50
54
|
}
|
|
51
55
|
});
|
|
52
56
|
|
|
53
|
-
this.client.on(
|
|
54
|
-
this.log(
|
|
57
|
+
this.client.on("connect", async () => {
|
|
58
|
+
this.log("TCP connection established with the server.");
|
|
55
59
|
this.connected = true;
|
|
56
|
-
|
|
60
|
+
|
|
57
61
|
const promiseClient = new PromiseSocket(this.client);
|
|
58
62
|
|
|
59
63
|
let command = Utils.encode(0, 0, 401, 0, "");
|
|
@@ -66,7 +70,7 @@ module.exports = (RED) => {
|
|
|
66
70
|
packet = await promiseClient.read();
|
|
67
71
|
this.info = Utils.decode(packet);
|
|
68
72
|
|
|
69
|
-
|
|
73
|
+
let numAntennas = 8 * this.status.stackReach;
|
|
70
74
|
for (let index = 1; index <= numAntennas; ++index) {
|
|
71
75
|
let command = Utils.encode(0, 0, 412, 0, index.toString());
|
|
72
76
|
await promiseClient.write(command);
|
|
@@ -85,12 +89,18 @@ module.exports = (RED) => {
|
|
|
85
89
|
}
|
|
86
90
|
this.updatesEventEmitter.emit("bands");
|
|
87
91
|
|
|
88
|
-
this.client.on(
|
|
92
|
+
this.client.on("data", (packet) => {
|
|
89
93
|
let decoded = Utils.decode(packet);
|
|
90
|
-
if(decoded.command == 401) {
|
|
91
|
-
this.status = {
|
|
94
|
+
if (decoded.command == 401) {
|
|
95
|
+
this.status = {
|
|
96
|
+
...this.status,
|
|
97
|
+
...Utils.decode(packet),
|
|
98
|
+
};
|
|
92
99
|
this.refresh = (this.refresh + 1) % 1500;
|
|
93
|
-
this.updatesEventEmitter.emit(
|
|
100
|
+
this.updatesEventEmitter.emit(
|
|
101
|
+
"status",
|
|
102
|
+
this.refresh == 0
|
|
103
|
+
);
|
|
94
104
|
}
|
|
95
105
|
});
|
|
96
106
|
|
|
@@ -102,24 +112,25 @@ module.exports = (RED) => {
|
|
|
102
112
|
|
|
103
113
|
this.forceUpdate();
|
|
104
114
|
this.updatesEventEmitter.emit("connected");
|
|
105
|
-
})
|
|
115
|
+
});
|
|
106
116
|
|
|
107
|
-
this.client.on(
|
|
117
|
+
this.client.on("error", (err) => {
|
|
108
118
|
this.warn(err);
|
|
109
119
|
});
|
|
110
120
|
|
|
111
|
-
this.on(
|
|
121
|
+
this.on("close", (done) => {
|
|
112
122
|
clearInterval(this.interval);
|
|
113
123
|
clearTimeout(this.timer);
|
|
114
124
|
this.autoConnect = false;
|
|
115
125
|
this.connected = false;
|
|
116
126
|
this.client.end();
|
|
127
|
+
this.forceUpdate();
|
|
117
128
|
done();
|
|
118
129
|
});
|
|
119
130
|
}
|
|
120
131
|
|
|
121
132
|
connect() {
|
|
122
|
-
if(this.autoConnect && !this.connected & !this.client.connecting) {
|
|
133
|
+
if (this.autoConnect && !this.connected & !this.client.connecting) {
|
|
123
134
|
this.client.connect(this.port, this.host);
|
|
124
135
|
}
|
|
125
136
|
}
|
|
@@ -129,5 +140,5 @@ module.exports = (RED) => {
|
|
|
129
140
|
}
|
|
130
141
|
}
|
|
131
142
|
|
|
132
|
-
RED.nodes.registerType("antenna-genius-server",AntennaGeniusServerNode);
|
|
133
|
-
}
|
|
143
|
+
RED.nodes.registerType("antenna-genius-server", AntennaGeniusServerNode);
|
|
144
|
+
};
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"id": "dae0c396900b679c",
|
|
4
|
+
"type": "tab",
|
|
5
|
+
"label": "Flow 1",
|
|
6
|
+
"disabled": false,
|
|
7
|
+
"info": "",
|
|
8
|
+
"env": []
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"id": "490d38d6edc8b3d3",
|
|
12
|
+
"type": "ui_button",
|
|
13
|
+
"z": "dae0c396900b679c",
|
|
14
|
+
"name": "A",
|
|
15
|
+
"group": "c4ec36e264004fa8",
|
|
16
|
+
"order": 4,
|
|
17
|
+
"width": "2",
|
|
18
|
+
"height": "1",
|
|
19
|
+
"passthru": false,
|
|
20
|
+
"label": "{{payload.name}}",
|
|
21
|
+
"tooltip": "",
|
|
22
|
+
"color": "",
|
|
23
|
+
"bgcolor": "{{payload.background}}",
|
|
24
|
+
"className": "",
|
|
25
|
+
"icon": "",
|
|
26
|
+
"payload": "true",
|
|
27
|
+
"payloadType": "bool",
|
|
28
|
+
"topic": "topic",
|
|
29
|
+
"topicType": "msg",
|
|
30
|
+
"x": 650,
|
|
31
|
+
"y": 160,
|
|
32
|
+
"wires": [
|
|
33
|
+
[
|
|
34
|
+
"21cbfe61e047667a"
|
|
35
|
+
]
|
|
36
|
+
]
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"id": "4ce85a4a6d600cbb",
|
|
40
|
+
"type": "ui_button",
|
|
41
|
+
"z": "dae0c396900b679c",
|
|
42
|
+
"name": "B",
|
|
43
|
+
"group": "c4ec36e264004fa8",
|
|
44
|
+
"order": 6,
|
|
45
|
+
"width": "2",
|
|
46
|
+
"height": "1",
|
|
47
|
+
"passthru": false,
|
|
48
|
+
"label": "{{payload.name}}",
|
|
49
|
+
"tooltip": "",
|
|
50
|
+
"color": "",
|
|
51
|
+
"bgcolor": "{{payload.background}}",
|
|
52
|
+
"className": "",
|
|
53
|
+
"icon": "",
|
|
54
|
+
"payload": "true",
|
|
55
|
+
"payloadType": "bool",
|
|
56
|
+
"topic": "topic",
|
|
57
|
+
"topicType": "msg",
|
|
58
|
+
"x": 730,
|
|
59
|
+
"y": 200,
|
|
60
|
+
"wires": [
|
|
61
|
+
[
|
|
62
|
+
"21cbfe61e047667a"
|
|
63
|
+
]
|
|
64
|
+
]
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"id": "4fbaa2cf09147758",
|
|
68
|
+
"type": "ui_text",
|
|
69
|
+
"z": "dae0c396900b679c",
|
|
70
|
+
"group": "c4ec36e264004fa8",
|
|
71
|
+
"order": 2,
|
|
72
|
+
"width": 0,
|
|
73
|
+
"height": 0,
|
|
74
|
+
"name": "",
|
|
75
|
+
"label": "Radio A | Radio B",
|
|
76
|
+
"format": "{{msg.payload.bandLabelA}} | {{msg.payload.bandLabelB}}",
|
|
77
|
+
"layout": "col-center",
|
|
78
|
+
"className": "",
|
|
79
|
+
"x": 690,
|
|
80
|
+
"y": 100,
|
|
81
|
+
"wires": []
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"id": "8f71346072320a9f",
|
|
85
|
+
"type": "ui_button",
|
|
86
|
+
"z": "dae0c396900b679c",
|
|
87
|
+
"name": "A",
|
|
88
|
+
"group": "c4ec36e264004fa8",
|
|
89
|
+
"order": 8,
|
|
90
|
+
"width": "2",
|
|
91
|
+
"height": "1",
|
|
92
|
+
"passthru": false,
|
|
93
|
+
"label": "{{payload.name}}",
|
|
94
|
+
"tooltip": "",
|
|
95
|
+
"color": "",
|
|
96
|
+
"bgcolor": "{{payload.background}}",
|
|
97
|
+
"className": "",
|
|
98
|
+
"icon": "",
|
|
99
|
+
"payload": "true",
|
|
100
|
+
"payloadType": "bool",
|
|
101
|
+
"topic": "topic",
|
|
102
|
+
"topicType": "msg",
|
|
103
|
+
"x": 650,
|
|
104
|
+
"y": 240,
|
|
105
|
+
"wires": [
|
|
106
|
+
[
|
|
107
|
+
"21cbfe61e047667a"
|
|
108
|
+
]
|
|
109
|
+
]
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"id": "68254444f1308033",
|
|
113
|
+
"type": "ui_button",
|
|
114
|
+
"z": "dae0c396900b679c",
|
|
115
|
+
"name": "B",
|
|
116
|
+
"group": "c4ec36e264004fa8",
|
|
117
|
+
"order": 10,
|
|
118
|
+
"width": "2",
|
|
119
|
+
"height": "1",
|
|
120
|
+
"passthru": false,
|
|
121
|
+
"label": "{{payload.name}}",
|
|
122
|
+
"tooltip": "",
|
|
123
|
+
"color": "",
|
|
124
|
+
"bgcolor": "{{payload.background}}",
|
|
125
|
+
"className": "",
|
|
126
|
+
"icon": "",
|
|
127
|
+
"payload": "true",
|
|
128
|
+
"payloadType": "bool",
|
|
129
|
+
"topic": "topic",
|
|
130
|
+
"topicType": "msg",
|
|
131
|
+
"x": 730,
|
|
132
|
+
"y": 280,
|
|
133
|
+
"wires": [
|
|
134
|
+
[
|
|
135
|
+
"21cbfe61e047667a"
|
|
136
|
+
]
|
|
137
|
+
]
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
"id": "78617c107783edfa",
|
|
141
|
+
"type": "antenna-genius-band-labels",
|
|
142
|
+
"z": "dae0c396900b679c",
|
|
143
|
+
"name": "",
|
|
144
|
+
"server": "",
|
|
145
|
+
"x": 400,
|
|
146
|
+
"y": 100,
|
|
147
|
+
"wires": [
|
|
148
|
+
[
|
|
149
|
+
"4fbaa2cf09147758"
|
|
150
|
+
]
|
|
151
|
+
]
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
"id": "c273fac278c6addb",
|
|
155
|
+
"type": "antenna-genius-antenna-status",
|
|
156
|
+
"z": "dae0c396900b679c",
|
|
157
|
+
"name": "",
|
|
158
|
+
"server": "",
|
|
159
|
+
"antennaNb": "1",
|
|
160
|
+
"x": 390,
|
|
161
|
+
"y": 200,
|
|
162
|
+
"wires": [
|
|
163
|
+
[
|
|
164
|
+
"490d38d6edc8b3d3"
|
|
165
|
+
],
|
|
166
|
+
[
|
|
167
|
+
"4ce85a4a6d600cbb"
|
|
168
|
+
]
|
|
169
|
+
]
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
"id": "21cbfe61e047667a",
|
|
173
|
+
"type": "antenna-genius-activate-antenna",
|
|
174
|
+
"z": "dae0c396900b679c",
|
|
175
|
+
"name": "",
|
|
176
|
+
"server": "",
|
|
177
|
+
"x": 1080,
|
|
178
|
+
"y": 180,
|
|
179
|
+
"wires": []
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
"id": "9efa627cb00ca277",
|
|
183
|
+
"type": "antenna-genius-antenna-status",
|
|
184
|
+
"z": "dae0c396900b679c",
|
|
185
|
+
"name": "",
|
|
186
|
+
"server": "",
|
|
187
|
+
"antennaNb": "2",
|
|
188
|
+
"x": 390,
|
|
189
|
+
"y": 280,
|
|
190
|
+
"wires": [
|
|
191
|
+
[
|
|
192
|
+
"8f71346072320a9f"
|
|
193
|
+
],
|
|
194
|
+
[
|
|
195
|
+
"68254444f1308033"
|
|
196
|
+
]
|
|
197
|
+
]
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
"id": "8233785eeb4f52ab",
|
|
201
|
+
"type": "comment",
|
|
202
|
+
"z": "dae0c396900b679c",
|
|
203
|
+
"name": "Antennas",
|
|
204
|
+
"info": "",
|
|
205
|
+
"x": 660,
|
|
206
|
+
"y": 40,
|
|
207
|
+
"wires": []
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
"id": "c4ec36e264004fa8",
|
|
211
|
+
"type": "ui_group",
|
|
212
|
+
"name": "Antenna Genius",
|
|
213
|
+
"tab": "ac6e9d7b975180d8",
|
|
214
|
+
"order": 1,
|
|
215
|
+
"disp": false,
|
|
216
|
+
"width": "4",
|
|
217
|
+
"collapse": false,
|
|
218
|
+
"className": ""
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
"id": "ac6e9d7b975180d8",
|
|
222
|
+
"type": "ui_tab",
|
|
223
|
+
"name": "Antenna Genius",
|
|
224
|
+
"icon": "dashboard",
|
|
225
|
+
"order": 1,
|
|
226
|
+
"disabled": false,
|
|
227
|
+
"hidden": false
|
|
228
|
+
}
|
|
229
|
+
]
|
|
Binary file
|