117 lines
2.9 KiB
JavaScript
117 lines
2.9 KiB
JavaScript
let wasm_inited_resolve;
|
|
const wasm_inited = new Promise((resolve) => {wasm_inited_resolve = resolve;});
|
|
|
|
document.addEventListener("wasm-loaded", () => {
|
|
wasm_inited_resolve(wasm_bindgen)
|
|
});
|
|
|
|
document.addEventListener("alpine:init", () => {
|
|
Alpine.store("mqtt", {
|
|
connected: false,
|
|
_client: null,
|
|
_topic: null,
|
|
_c: null,
|
|
|
|
_pendingPromises: {},
|
|
|
|
sendTime(time) {
|
|
if (!this.connected) return null;
|
|
|
|
const id = uuidv4();
|
|
const promise = new Promise((resolve, reject) => {this._pendingPromises[id] = [resolve, reject]});
|
|
this._publish({
|
|
id: id, // used to prevent replay attacks and to identify confirm messages
|
|
kind: "Time", // can be "time" or "confirm"
|
|
time: time, // only used for "time"
|
|
});
|
|
|
|
return promise;
|
|
},
|
|
|
|
async connect() {
|
|
if (this.connected) return;
|
|
|
|
const password = Alpine.store("localState").password;
|
|
const that = this;
|
|
const brokerDomain = "broker.emqx.io";
|
|
const url = `wss://${brokerDomain}:8084/mqtt`;
|
|
|
|
if (!password) return false;
|
|
|
|
const {Crypto} = await wasm_inited;
|
|
|
|
Alpine.store("localState")._state = 5;
|
|
|
|
// derive key from password
|
|
this._c = new Crypto(password, brokerDomain);
|
|
|
|
console.log("Test", this._encrypt("test"));
|
|
|
|
this._topic = Crypto.sha256(
|
|
this._encrypt(`org.speedclimbing.ok-ready-go.${password}`)
|
|
).toString();
|
|
|
|
console.log("Connecting to MQTT broker...");
|
|
console.log("topic:", this._topic);
|
|
|
|
const options = {
|
|
// Clean session
|
|
clean: true,
|
|
connectTimeout: 4000,
|
|
};
|
|
|
|
this._client = mqtt.connect(url, options);
|
|
|
|
this._client.on("connect", () => {
|
|
Alpine.store("localState")._state = 0;
|
|
|
|
that._client.subscribe(that._topic);
|
|
this.connected = true;
|
|
});
|
|
|
|
this._client.on("message", (topic, message) => {
|
|
// message is Buffer
|
|
message = that._decrypt(message.toString());
|
|
const data = JSON.parse(message);
|
|
|
|
if (topic !== that._topic || data.kind !== "Confirm" || Object.keys(this._pendingPromises).indexOf(data.id) === -1) return;
|
|
|
|
console.log("<<< ", data);
|
|
this._pendingPromises[data.id][0]();
|
|
});
|
|
},
|
|
|
|
disconnect() {
|
|
if(!this.connected) return;
|
|
|
|
this._client.end(true);
|
|
|
|
this._client = null;
|
|
this.connected = false;
|
|
this._topic = null;
|
|
|
|
for (const promiseId in this._pendingPromises) {
|
|
this._pendingPromises[promiseId][1]();
|
|
}
|
|
|
|
this._pendingPromises = {};
|
|
},
|
|
|
|
_publish(data) {
|
|
const encryptedData = this._encrypt(JSON.stringify(data));
|
|
console.log(">>> ", data);
|
|
this._client.publish(this._topic, encryptedData, {
|
|
qos: 1,
|
|
retain: false,
|
|
});
|
|
},
|
|
|
|
_encrypt(data) {
|
|
return this._c.encrypt(data);
|
|
},
|
|
|
|
_decrypt(data) {
|
|
return this._c.decrypt(data);
|
|
},
|
|
});
|
|
});
|