V0.5.9 Arroyo Toad

There's a bug during conversion from buffer to unix timestamp
This commit is contained in:
Christian Risi 2024-12-06 19:12:01 +00:00
parent 7ffa84fa3e
commit e9abeb9bb6
13 changed files with 258 additions and 0 deletions

View File

@ -11,6 +11,7 @@
"customizations": {
"vscode": {
"extensions": [
"denoland.vscode-deno",
"fabiospampinato.vscode-highlight",
"fabiospampinato.vscode-todo-plus"
]

Binary file not shown.

8
deno.json Normal file
View File

@ -0,0 +1,8 @@
{
"tasks": {
"dev": "deno run --watch ./src/main.ts"
},
"imports": {
"@std/assert": "jsr:@std/assert@1"
}
}

23
deno.lock generated Normal file
View File

@ -0,0 +1,23 @@
{
"version": "4",
"specifiers": {
"jsr:@std/assert@1": "1.0.9",
"jsr:@std/internal@^1.0.5": "1.0.5"
},
"jsr": {
"@std/assert@1.0.9": {
"integrity": "a9f0c611a869cc791b26f523eec54c7e187aab7932c2c8e8bea0622d13680dcd",
"dependencies": [
"jsr:@std/internal"
]
},
"@std/internal@1.0.5": {
"integrity": "54a546004f769c1ac9e025abd15a76b6671ddc9687e2313b67376125650dc7ba"
}
},
"workspace": {
"dependencies": [
"jsr:@std/assert@1"
]
}
}

12
src/classes/Field.ts Normal file
View File

@ -0,0 +1,12 @@
export class Field {
public key: Uint8Array
public value: Uint8Array
constructor(
key: Uint8Array,
value: Uint8Array
) {
this.key = key
this.value = value
}
}

15
src/classes/Location.ts Normal file
View File

@ -0,0 +1,15 @@
export class DeviceLocation {
public x: bigint;
public y: bigint;
public z: bigint;
constructor(
x: bigint,
y: bigint,
z: bigint,
) {
this.x = x;
this.y = y;
this.z = z;
}
}

68
src/classes/Message.ts Normal file
View File

@ -0,0 +1,68 @@
import { DeviceType } from "../enums/DeviceType.ts";
import { MessageType } from "../enums/MessageType.ts";
import { SignatureType } from "../enums/SignatureType.ts";
import { Field } from "./Field.ts";
import { DeviceLocation } from "./Location.ts";
export class Message {
public version: number;
public messageType: MessageType;
public RESERVED: number;
public deviceType: DeviceType;
public signatureType: SignatureType;
public timestamp: bigint;
public deviceID: bigint;
public location: DeviceLocation;
public fields: Field[];
public signature: Uint8Array;
constructor(
version: number,
messageType: MessageType,
deviceType: DeviceType,
RESERVED: number,
signatureType: SignatureType,
timestamp: bigint,
deviceID: bigint,
location: DeviceLocation,
fields: Field[],
signature: Uint8Array,
) {
this.version = version;
this.messageType = messageType;
this.RESERVED = RESERVED;
this.deviceType = deviceType;
this.signatureType = signatureType;
this.timestamp = timestamp;
this.deviceID = deviceID;
this.location = location;
this.fields = fields;
this.signature = signature;
}
public toString() {
let description = `
Message ----------------------
\tVersion: \t${this.version}
\tMessage Type: \t${this.messageType}
\tDevice Type: \t${this.deviceType}
\tRESERVED: \t${this.RESERVED}
\tSignature Type: \t${this.signatureType}
\tTimestamp: \t${ new Date(Number(this.timestamp / 10000000n))}
\tDevice ID: \t${this.deviceID}
\tLocation: \tX: ${this.location.x}\tY: ${this.location.y}\tZ: ${this.location.z}
\tFields: \n`;
this.fields.forEach((element) => {
description += `\t\t${new TextDecoder().decode(element.key)}: ${
new TextDecoder().decode(element.value)
}\n`;
});
description +=`\tSignature: \t${new TextDecoder().decode(this.signature)}`
return description
}
}

4
src/enums/DeviceType.ts Normal file
View File

@ -0,0 +1,4 @@
export enum DeviceType {
EDGE_SENSOR = 0,
SCANNER_SENSOR = 1
}

8
src/enums/MessageType.ts Normal file
View File

@ -0,0 +1,8 @@
export enum MessageType {
KEEPALIVE = 0,
DATA = 1,
INFO = 2,
WARNING =50,
ERROR = 100,
CRITICAL = 255,
}

View File

@ -0,0 +1,3 @@
export enum SignatureType {
P521 = 10
}

1
src/mod.ts Normal file
View File

@ -0,0 +1 @@

103
src/utils/deserializer.ts Normal file
View File

@ -0,0 +1,103 @@
import { Field } from "../classes/Field.ts";
import { Message } from "../classes/Message.ts";
import { DeviceType } from "../enums/DeviceType.ts";
import { MessageType } from "../enums/MessageType.ts";
import { SignatureType } from "../enums/SignatureType.ts";
import { DeviceLocation } from "../classes/Location.ts";
export function deserializerV1(buffer: ArrayBuffer) {
const version: number = new Uint8Array(buffer.slice(0, 1))[0];
// UGLY Force typecasting
const messageType: MessageType = MessageType[
MessageType[
new Uint8Array(buffer.slice(1, 2))[0]
] as keyof typeof MessageType
];
// UGLY Force typecasting
const deviceType: DeviceType = DeviceType[
DeviceType[
new Uint8Array(buffer.slice(2, 3))[0]
] as keyof typeof DeviceType
];
const RESERVED: number = new Uint8Array(buffer.slice(3, 4))[0];
// UGLY Force typecasting
const signatureType: number = SignatureType[
SignatureType[
new Uint32Array(buffer.slice(4, 8))[0]
] as keyof typeof SignatureType
];
const timestamp: bigint = new BigUint64Array(buffer.slice(8, 16))[0];
// UGLY: sum the 2 bigints to a sing bigint
const deviceID_Buffer = new BigUint64Array(buffer.slice(16, 32));
const deviceID: bigint = (deviceID_Buffer[1] << 64n) + deviceID_Buffer[0];
const locX: bigint = new BigUint64Array(buffer.slice(32, 40))[0];
const locY: bigint = new BigUint64Array(buffer.slice(40, 48))[0];
const locZ: bigint = new BigUint64Array(buffer.slice(48, 56))[0];
let index = 56;
let MORE_FIELDS = true;
let fields: Field[] = Array<Field>();
while (MORE_FIELDS) {
const nextchunk = new BigUint64Array(buffer.slice(index, index + 8))[0];
if (nextchunk === 0n) {
MORE_FIELDS = false;
continue;
}
const key_value_counts = new Uint32Array(buffer.slice(index, index + 8));
const key_count = key_value_counts[0];
const value_count = key_value_counts[1];
index += 8;
const key = new Uint8Array(buffer.slice(index, index + key_count));
index += key_count;
const value = new Uint8Array(buffer.slice(index, index + value_count));
index += value_count;
fields.push(new Field(key, value));
}
const paddingBytes = (8 - (index % 8)) % 8;
index += paddingBytes + 8;
const signature = new Uint8Array(buffer.slice(index))
if (signature.length != signatureBytesMapper(signatureType)) {
throw new Error("This signature is not valid")
}
return new Message(
version,
messageType,
deviceType,
RESERVED,
signatureType,
timestamp,
deviceID,
new DeviceLocation(locX, locY, locZ),
fields,
signature
)
}
export function signatureBytesMapper(signatureType: SignatureType) {
switch (signatureType) {
case SignatureType.P521 : {
return 132
}
}
}

12
tests/main_test.ts Normal file
View File

@ -0,0 +1,12 @@
import { assertEquals } from "@std/assert";
import { deserializerV1 } from "../src/utils/deserializer.ts";
Deno.test(async function deserializerV1Test() {
const messageBuffer = (await Deno.readFile("./Private/Message.bin")).buffer
const msg = deserializerV1(messageBuffer)
console.log(msg.toString())
//Assert
})