forked from rycont/pm-b310-w2-reversing-deno
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
94 lines (82 loc) · 2.34 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import {
Client,
Event,
Packet,
} from "https://deno.land/x/[email protected]/mods.ts";
const hex2dec = (data: number[]) =>
new Float32Array(new Uint8Array([...data]).buffer)[0];
function chunk(arr: number[], n: number) {
return arr.reduce(
(acc, _, i) => (i % n ? acc : [...acc, arr.slice(i, i + n)]),
[] as number[][]
);
}
const INFO_KEYS = [
"voltage",
"current",
"frequency",
"power-factor",
"consumtion",
"accumulate",
"price",
"co2",
] as const;
export type Info = Record<typeof INFO_KEYS[number], number>;
export const createAIPMConnector = async (connectionInfo: {
mac: string;
ip: string;
port?: number;
}) => {
const client = new Client({
hostname: connectionInfo.ip,
port: connectionInfo.port || 5000,
});
await client.connect();
const schemeVersion = 0xfa;
const serializedMac = [...connectionInfo.mac].map((e) => e.charCodeAt(0));
function send(message: number[]) {
const buffer = new Uint8Array(25);
buffer.set([schemeVersion, ...serializedMac, ...message]);
return client.write(buffer);
}
let infoListener: (info: Info) => void;
client.addListener(Event.receive, async (c, d: Packet) => {
const [command, ...data] = d.data.slice(7);
if (command === 0x51) {
await send([0x58, 0x16, 0x01, 0x0e, 0x06, 0xfb, 0x46, 0x0d]);
}
if (command === 0x5a) {
await send([0x74, 0x50, 0x75, 0x73, 0x68, 0xfb, 0x4b, 0x0d]);
}
if (command === 0x41) {
await send([0x50, 0x01, 0x00, 0x00, 0xfb, 0x52, 0x0d]);
}
if (command === 0x76) {
await send([0x50, 0x01, 0x00, 0x00, 0xfb, 0x52, 0x0d]);
await send([0x50, 0x01, 0x00, 0x00, 0xfb, 0x52, 0x0d]);
}
if (command === 0x40) {
if (!infoListener) return;
infoListener(
Object.fromEntries(
chunk(data.slice(0, INFO_KEYS.length * 4), 4)
.map(hex2dec)
.map((v, i) => [INFO_KEYS[i], v])
) as Info
);
await send([0x74, 0x50, 0x75, 0x73, 0x68, 0xfb, 0x4b, 0x0d]);
}
});
return {
async on() {
return await send([0x57, 0x01, 0xfb, 0xf3, 0x0d]);
},
async off() {
return await send([0x57, 0xa4, 0xfb, 0xf0, 0x0d]);
},
async getInfoForever(listener: typeof infoListener) {
infoListener = listener;
return await send([0x51, 0x18, 0x39, 0x00, 0xfb, 0x71, 0x0d]);
},
};
};