Skip to content

Commit

Permalink
Add support for color theme messages (#35)
Browse files Browse the repository at this point in the history
* initial commit

* fix lint
  • Loading branch information
evertonstz authored Apr 19, 2024
1 parent 5ba4899 commit 0968cdd
Show file tree
Hide file tree
Showing 8 changed files with 305 additions and 36 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
"ts-node": "^10.9.2",
"typescript": "^5.2.2",
"vite": "^5.0.8",
"vitest": "^1.3.1"
"vitest": "^1.4.0"
},
"packageManager": "[email protected]+sha256.cea6d0bdf2de3a0549582da3983c70c92ffc577ff4410cbf190817ddc35137c2"
}
66 changes: 33 additions & 33 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export interface UsePaxBluetoothServicesState {
isListenerAdded: boolean;
};
readFromMainService: () => Promise<Pax.lib.messages.MessageAbs>;
writeToMainService: (message: Pax.lib.PaxEncryptedPacket) => Promise<void>;
writeToMainService: (packet: Pax.lib.PaxEncryptedPacket) => Promise<void>;
}

export const usePaxBluetoothServices = (
Expand Down
4 changes: 4 additions & 0 deletions src/pax/containers/api/get.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { ColorThemeMessage } from '@/pax/core/messages/ColorThemeMessage';

import {
ActualTemperatureMessage,
HeaterSetPointMessage,
Expand Down Expand Up @@ -29,6 +31,8 @@ export const decodeDecryptedPacket = (
return HeaterSetPointMessage.createWithPacket(packet);
case Messages.ATTRIBUTE_HEATING_STATE:
return new HeatingStateMessage(packet);
case Messages.ATTRIBUTE_COLOR_THEME:
return ColorThemeMessage.createWithPacket(packet);
default:
return new UnknownMessage(messageType, packet);
}
Expand Down
2 changes: 1 addition & 1 deletion src/pax/core/crypt/Pax3Imp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export class Pax3Imp extends PaxAbs {
} {
return {
iv: CryptoJS.enc.Hex.parse(hexPacket.slice(-32)),
hexPacketToDecrypt: CryptoJS.enc.Hex.parse(hexPacket.slice(0, 32)),
hexPacketToDecrypt: CryptoJS.enc.Hex.parse(hexPacket.slice(0, -32)),
};
}

Expand Down
153 changes: 153 additions & 0 deletions src/pax/core/messages/ColorThemeMessage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import { PaxDecryptedPacket } from '@/pax/containers/lib';
import { Messages } from '@/pax/shared/enums';
import { ColorMode, ColorTheme } from '@/pax/shared/types/colorTheme';

import { MessageAbs } from './MessageAbs';
import { ReadAndWriteMessageAbs } from './ReadAndWriteMessageAbs';

export class ColorThemeMessage
extends ReadAndWriteMessageAbs
implements MessageAbs
{
readonly theme: ColorTheme;
readonly messageType: Messages;
readonly packet: PaxDecryptedPacket;

constructor(
builder:
| ColorThemeMessageBuilderFromPacket<ColorThemeMessage>
| ColorThemeMessageBuilderFromValue<ColorThemeMessage>,
) {
super();
this.messageType = Messages.ATTRIBUTE_COLOR_THEME;
if (builder instanceof ColorThemeMessageBuilderFromPacket) {
this.packet = builder.getPacket();
const colorModesCount = this.packet.getUint8(1);

const colorModes: ColorMode[] = [];

for (let i = 0; i < colorModesCount; i++) {
const byteOffset = 2 + i * 8;
const colorBytes = new Uint8Array(this.packet.buffer, byteOffset, 8);
const colorMode = this.bytesToColorMode(colorBytes);
colorModes.push(colorMode);
}
const colorTheme = {
heating: colorModes[1],
regulating: colorModes[2],
standby: colorModes[3],
startup: colorModes[0],
};
this.theme = colorTheme;
} else if (builder instanceof ColorThemeMessageBuilderFromValue) {
this.theme = builder.getTheme();

const extractIntFromColorMode = (colorMode: ColorMode): number[] => {
return [
colorMode.color1.red,
colorMode.color1.green,
colorMode.color1.blue,
colorMode.color2.red,
colorMode.color2.green,
colorMode.color2.blue,
colorMode.animation,
colorMode.frequency,
];
};

const arr = new Uint8Array([
this.messageType,
Object.keys(this.theme).length,
...extractIntFromColorMode(this.theme.startup),
...extractIntFromColorMode(this.theme.heating),
...extractIntFromColorMode(this.theme.regulating),
...extractIntFromColorMode(this.theme.standby),
]);

const view = new PaxDecryptedPacket(
arr.buffer,
arr.byteOffset,
arr.byteLength,
);
view.setUint8(0, this.messageType);
this.packet = view;
} else {
throw new Error('Invalid builder');
}
}

bytesToColorMode(array: Uint8Array): ColorMode {
return {
animation: array[6],
color1: {
blue: array[2],
green: array[1],
red: array[0],
},
color2: {
blue: array[5],
green: array[4],
red: array[3],
},
frequency: array[7],
};
}

static createWithPacket(packet: PaxDecryptedPacket): ColorThemeMessage {
const builder = new ColorThemeMessageBuilderFromPacket<ColorThemeMessage>();
builder.setPacket(packet);
return new ColorThemeMessage(builder);
}

static createWithTheme(theme: ColorTheme): ColorThemeMessage {
const builder = new ColorThemeMessageBuilderFromValue<ColorThemeMessage>();
builder.setTheme(theme);
return new ColorThemeMessage(builder);
}
}

export class ColorThemeMessageBuilderFromPacket<T extends ColorThemeMessage> {
private packet?: PaxDecryptedPacket;

setPacket(packet: PaxDecryptedPacket): ColorThemeMessageBuilderFromPacket<T> {
this.packet = packet;
return this;
}

getPacket(): PaxDecryptedPacket {
if (!this.packet) {
throw new Error('Packet is not set');
}
return this.packet;
}

build(ctor: new (builder: ColorThemeMessageBuilderFromPacket<T>) => T): T {
if (!this.packet) {
throw new Error('Packet is not set');
}
return new ctor(this);
}
}

export class ColorThemeMessageBuilderFromValue<T extends ColorThemeMessage> {
private theme?: ColorTheme;

setTheme(theme: ColorTheme): ColorThemeMessageBuilderFromValue<T> {
this.theme = theme;
return this;
}

getTheme(): ColorTheme {
if (!this.theme) {
throw new Error('Theme is not set');
}
return this.theme;
}

build(ctor: new (builder: ColorThemeMessageBuilderFromValue<T>) => T): T {
if (!this.theme) {
throw new Error('Theme is not set');
}
return new ctor(this);
}
}
Loading

0 comments on commit 0968cdd

Please sign in to comment.