Skip to content

Commit

Permalink
refactor: replace xstate with a simple built-in state machine (#7460)
Browse files Browse the repository at this point in the history
  • Loading branch information
AlCalzone authored Dec 9, 2024
1 parent 6fe88f9 commit 6c10570
Show file tree
Hide file tree
Showing 18 changed files with 1,424 additions and 1,823 deletions.
2 changes: 0 additions & 2 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ updates:
# so only apply patch and minor updates automatically
- dependency-name: '@types/node'
update-types: ['version-update:semver-major']
# xstate usually requires manual intervention
- dependency-name: 'xstate'

- package-ecosystem: github-actions
directory: '/'
Expand Down
28 changes: 4 additions & 24 deletions packages/cc/src/cc/TransportServiceCC.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,10 @@ import type {
} from "@zwave-js/host/safe";
import { Bytes } from "@zwave-js/shared/safe";
import { buffer2hex } from "@zwave-js/shared/safe";
import {
type CCRaw,
type CCResponseRole,
CommandClass,
} from "../lib/CommandClass.js";
import { type CCRaw, CommandClass } from "../lib/CommandClass.js";
import {
CCCommand,
commandClass,
expectedCCResponse,
implementedVersion,
} from "../lib/CommandClassDecorators.js";
import { TransportServiceCommand } from "../lib/_Types.js";
Expand Down Expand Up @@ -81,7 +76,7 @@ export function isTransportServiceEncapsulation(
}

@CCCommand(TransportServiceCommand.FirstSegment)
// @expectedCCResponse(TransportServiceCCReport)
// Handling expected responses is done by the RX state machine
export class TransportServiceCCFirstSegment extends TransportServiceCC {
public constructor(
options: WithAddress<TransportServiceCCFirstSegmentOptions>,
Expand Down Expand Up @@ -227,7 +222,7 @@ export interface TransportServiceCCSubsequentSegmentOptions
}

@CCCommand(TransportServiceCommand.SubsequentSegment)
// @expectedCCResponse(TransportServiceCCReport)
// Handling expected responses is done by the RX state machine
export class TransportServiceCCSubsequentSegment extends TransportServiceCC {
public constructor(
options: WithAddress<TransportServiceCCSubsequentSegmentOptions>,
Expand Down Expand Up @@ -465,23 +460,8 @@ export interface TransportServiceCCSegmentRequestOptions {
datagramOffset: number;
}

function testResponseForSegmentRequest(
sent: TransportServiceCCSegmentRequest,
received: TransportServiceCC,
): CCResponseRole {
return (
(sent.datagramOffset === 0
&& received instanceof TransportServiceCCFirstSegment
&& received.sessionId === sent.sessionId)
|| (sent.datagramOffset > 0
&& received instanceof TransportServiceCCSubsequentSegment
&& sent.datagramOffset === received.datagramOffset
&& received.sessionId === sent.sessionId)
);
}

@CCCommand(TransportServiceCommand.SegmentRequest)
@expectedCCResponse(TransportServiceCC, testResponseForSegmentRequest)
// Handling expected responses is done by the RX state machine
export class TransportServiceCCSegmentRequest extends TransportServiceCC {
public constructor(
options: WithAddress<TransportServiceCCSegmentRequestOptions>,
Expand Down
88 changes: 88 additions & 0 deletions packages/core/src/fsm/FSM.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
export interface StateMachineTransition<
State extends StateMachineState,
Effect = undefined,
> {
effect?: Effect;
newState: State;
}

export interface StateMachineState {
value: number | string;
done?: boolean;
}

export interface StateMachineInput {
value: number | string;
}

export type StateMachineTransitionMap<
State extends StateMachineState,
Input extends StateMachineInput,
Effect = undefined,
> = (
state: State,
) => (
input: Input,
) => StateMachineTransition<State, Effect | undefined> | undefined;

export type InferStateMachineTransitions<
T extends StateMachine<any, any, any>,
> = T extends StateMachine<infer S, infer I, infer E>
? StateMachineTransitionMap<S, I, E | undefined>
: never;

export class StateMachine<
State extends StateMachineState,
Input extends StateMachineInput,
Effect = undefined,
> {
public constructor(
initialState: State,
transitions: StateMachineTransitionMap<
State,
Input,
Effect | undefined
>,
) {
this._initial = this._state = initialState;
this.transitions = transitions;
}

protected transitions: StateMachineTransitionMap<
State,
Input,
Effect | undefined
>;

/** Restarts the machine from the initial state */
public restart(): void {
this._state = this._initial;
}

/** Determines the next transition to take */
public next(
input: Input,
): StateMachineTransition<State, Effect | undefined> | undefined {
if (this._state.done) return;
return this.transitions(this._state)(input);
}

/** Transitions the machine to the next state. This does not execute effects */
public transition(next?: State): void {
// Allow some convenience by passing the transition's next state directly
if (next == undefined) return;
this._state = next;
}

private _initial: State;
private _state: State;
/** Returns the current state of the state machine */
public get state(): State {
return this._state;
}

/** Returns whether this state machine is done */
public get done(): boolean {
return !!this._state.done;
}
}
1 change: 1 addition & 0 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export * from "./crypto/index.node.js";
export * from "./definitions/index.js";
export * from "./dsk/index.js";
export * from "./error/ZWaveError.js";
export * from "./fsm/FSM.js";
export * from "./log/Controller.js";
export * from "./log/shared.js";
export * from "./log/shared_safe.js";
Expand Down
4 changes: 1 addition & 3 deletions packages/zwave-js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,7 @@
"semver": "^7.6.3",
"serialport": "^12.0.0",
"source-map-support": "^0.5.21",
"winston": "^3.15.0",
"xstate": "4.38.3"
"winston": "^3.15.0"
},
"devDependencies": {
"@alcalzone/esm2cjs": "^1.4.1",
Expand All @@ -130,7 +129,6 @@
"@types/semver": "^7.5.8",
"@types/sinon": "^17.0.3",
"@types/source-map-support": "^0.5.10",
"@xstate/test": "^0.5.1",
"@zwave-js/maintenance": "workspace:*",
"@zwave-js/transformers": "workspace:*",
"del-cli": "^6.0.0",
Expand Down
Loading

0 comments on commit 6c10570

Please sign in to comment.