145 lines
2.9 KiB
JavaScript
145 lines
2.9 KiB
JavaScript
class EventEmitter {
|
|
constructor() {
|
|
this.events = {};
|
|
}
|
|
|
|
on(event, listener) {
|
|
if (!this.events[event]) {
|
|
this.events[event] = [];
|
|
}
|
|
this.events[event].push(listener);
|
|
}
|
|
|
|
emit(event, ...args) {
|
|
if (this.events[event]) {
|
|
this.events[event].forEach((listener) => listener(...args));
|
|
}
|
|
}
|
|
|
|
removeAllListeners() {
|
|
this.events = {};
|
|
}
|
|
}
|
|
|
|
// Convert Node.js module system to ES6 module system
|
|
export class NotConnectedError extends Error {
|
|
constructor(client) {
|
|
super("Client not connected");
|
|
this.client = client;
|
|
}
|
|
}
|
|
|
|
export const Polarity = {
|
|
Negative: 0,
|
|
Positive: 1,
|
|
};
|
|
|
|
export const Region = {
|
|
Unknown: 0,
|
|
Europe: 1,
|
|
Oceania: 2,
|
|
NorthAmerica: 3,
|
|
Asia: 4,
|
|
SouthAmerica: 5,
|
|
};
|
|
|
|
export class Client extends EventEmitter {
|
|
constructor(socketFactory) {
|
|
super();
|
|
this.socketFactory = socketFactory;
|
|
}
|
|
|
|
getSocket() {
|
|
return this.socket;
|
|
}
|
|
|
|
connect(url = this.generateRandomConnectionUrl()) {
|
|
const socket = (this.socket = this.socketFactory.make(url));
|
|
socket.onmessage = (event) => {
|
|
const rawData = this.decode(event.data);
|
|
|
|
this.emit("data", this.buildStrikeData(JSON.parse(rawData)));
|
|
};
|
|
socket.onopen = () => {
|
|
this.sendJSON({ a: 111 });
|
|
this.emit("connect", socket);
|
|
};
|
|
socket.onerror = (err) => this.emit("error", err);
|
|
}
|
|
|
|
close() {
|
|
if (!this.socket) {
|
|
throw new NotConnectedError(this);
|
|
}
|
|
this.socket.close();
|
|
this.removeAllListeners();
|
|
}
|
|
|
|
processRawLocation(location) {
|
|
return {
|
|
latitude: location.lat,
|
|
longitude: location.lon,
|
|
altitude: location.alt,
|
|
};
|
|
}
|
|
|
|
buildStrikeData(strike) {
|
|
return {
|
|
location: this.processRawLocation(strike),
|
|
deviation: strike.mds,
|
|
delay: strike.delay,
|
|
time: new Date(Math.floor(strike.time / 1e6)),
|
|
detectors: strike.sig.map((rawDec) => ({
|
|
id: rawDec.sta,
|
|
location: this.processRawLocation(rawDec),
|
|
status: rawDec.status,
|
|
delay: rawDec.time,
|
|
})),
|
|
polarity: strike.pol > 0 ? Polarity.Positive : Polarity.Negative,
|
|
maxDeviation: strike.mds,
|
|
maxCircularGap: strike.mcg,
|
|
region: strike.region,
|
|
};
|
|
}
|
|
|
|
decode(b) {
|
|
let a,
|
|
e = {},
|
|
d = b.split(""),
|
|
c = d[0],
|
|
f = c,
|
|
g = [c],
|
|
h = 256,
|
|
o = h;
|
|
|
|
for (let i = 1; i < d.length; i++) {
|
|
let charCode = d[i].charCodeAt(0);
|
|
a = h > charCode ? d[i] : e[charCode] ? e[charCode] : f + c;
|
|
g.push(a);
|
|
c = a.charAt(0);
|
|
e[o] = f + c;
|
|
o++;
|
|
f = a;
|
|
}
|
|
|
|
return g.join("");
|
|
}
|
|
|
|
sendJSON(data) {
|
|
this.socket.send(JSON.stringify(data));
|
|
}
|
|
|
|
generateRandomConnectionUrl() {
|
|
const knownServerIds = [1, 7, 8];
|
|
return `wss://ws${
|
|
knownServerIds[Math.floor(Math.random() * knownServerIds.length)]
|
|
}.blitzortung.org:443/`;
|
|
}
|
|
}
|
|
|
|
export class BrowserSocketFactory {
|
|
make(url) {
|
|
return new WebSocket(url);
|
|
}
|
|
}
|