initial release of Alex2Node
This commit is contained in:
parent
0804bd7397
commit
4eb2a84d72
20 changed files with 2047 additions and 3 deletions
131
src/Alex2Node.ts
Normal file
131
src/Alex2Node.ts
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
import mqtt, { MqttClient } from "mqtt";
|
||||
import Device from "./Device";
|
||||
|
||||
class Alex2MQTT {
|
||||
private client: MqttClient | null = null;
|
||||
private devices: Device[] = [];
|
||||
private MqttHost = "mqtt://Alex2MQTT.stormysdream.club";
|
||||
|
||||
constructor(
|
||||
private username: string,
|
||||
private password: string,
|
||||
private rootTopic: string,
|
||||
private debugLogging: boolean
|
||||
) {}
|
||||
|
||||
connect(): void {
|
||||
const options = {
|
||||
username: this.username,
|
||||
password: this.password,
|
||||
};
|
||||
|
||||
this.client = mqtt.connect(this.MqttHost, options);
|
||||
|
||||
this.client.on("connect", () => {
|
||||
if (this.debugLogging) {
|
||||
console.log("[Alex2Node.ts] Connected to MQTT broker");
|
||||
}
|
||||
|
||||
this.client!.subscribe(this.rootTopic + "/#", (err) => {
|
||||
if (this.debugLogging && !err) {
|
||||
console.log("[Alex2Node.ts] Subscribed to topics");
|
||||
}
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
this.client.on("message", (topic: string, message: Buffer) => {
|
||||
if (this.debugLogging) {
|
||||
console.log(`[Alex2Node.ts] MQTT Message Received`);
|
||||
console.log(` Topic: ${topic}`);
|
||||
console.log(` Payload: ${message.toString()}`);
|
||||
}
|
||||
if (topic == `${this.rootTopic}/discover`) {
|
||||
if (this.debugLogging) {
|
||||
console.log(
|
||||
"[Alex2Node.ts] Discovery request received, getting device json..."
|
||||
);
|
||||
}
|
||||
const deviceArray = this.devices.map((device) => device.getJSON());
|
||||
|
||||
if (deviceArray.length > 0) {
|
||||
this.client!.publish(
|
||||
topic + "_r",
|
||||
JSON.stringify(deviceArray),
|
||||
(err) => {
|
||||
if (err) {
|
||||
throw err;
|
||||
} else if (this.debugLogging) {
|
||||
console.log(
|
||||
`[Alex2Node.ts] Discovery payloads published to ${
|
||||
topic + "_r"
|
||||
}`
|
||||
);
|
||||
console.log(deviceArray);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
} else if (topic.split("/").length == 3) {
|
||||
const [root, endpointId, directiveType] = topic.split("/");
|
||||
if (directiveType != "alexaDirective") {
|
||||
return;
|
||||
}
|
||||
const device = this.devices.find((d) => d.endpointId === endpointId);
|
||||
if (!device) {
|
||||
if (this.debugLogging) {
|
||||
console.warn(
|
||||
`[Alex2Node.ts] No device found for endpointId: ${endpointId}`
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
let payload;
|
||||
try {
|
||||
payload = JSON.parse(message.toString());
|
||||
} catch (e) {
|
||||
console.error(`[Alex2Node.ts] Failed to parse payload JSON`, e);
|
||||
return;
|
||||
}
|
||||
if (
|
||||
payload.header &&
|
||||
payload.header.namespace === "Alexa" &&
|
||||
payload.header.name === "ReportState"
|
||||
) {
|
||||
if (this.debugLogging) {
|
||||
console.log(
|
||||
`[Alex2Node.ts] ReportState directive for device ${endpointId}`
|
||||
);
|
||||
}
|
||||
device.emit("ReportState", payload);
|
||||
}else{
|
||||
device.emit("Event", payload,payload.header.namespace);
|
||||
}
|
||||
}
|
||||
});
|
||||
this.client.on("error", (err: Error) => {
|
||||
if (this.debugLogging) {
|
||||
console.error("[Alex2Node.ts] Connection failed:", err);
|
||||
}
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
||||
registerDevice(name: string, endpointId: string): Device {
|
||||
if (!this.client) {
|
||||
throw new Error("Must call connect before creating devices");
|
||||
}
|
||||
if (this.debugLogging) {
|
||||
console.log(
|
||||
`[Alex2Node.ts] Creating new device with endpoint: ${endpointId}`
|
||||
);
|
||||
}
|
||||
const device = new Device(this.client!, this.rootTopic, name, endpointId);
|
||||
this.devices.push(device);
|
||||
return device;
|
||||
}
|
||||
}
|
||||
|
||||
export default Alex2MQTT;
|
||||
Loading…
Add table
Add a link
Reference in a new issue