Skip to content

Commit

Permalink
Allow setting/disabling Emergency Stop during setup/via Serial comman…
Browse files Browse the repository at this point in the history
…ds (#269)

* Upload port of @nullstalgia 's implementation

Title: Allow setting/disabling Emergency Stop during setup/via Serial commands

Date: April 19th 2024
Co-Authored-By: nullstalgia <[email protected]>

* Read from config and fix gpio num types

* Add SerialInput handler

* Remove STD's from integers

* Use intconv for SerialInputHandler

* Update schemas

* Remove annoying unnecessary warning

* Finish EStop config implementation

* More work is needed.... rip

* Fix extra logging areas

* Fix panic call

* Use new convert methods

* Undo formatting changes in Common.h

* Update schemas

* Fix argument order, and sort all remaining orders

* Revert to default config if null

* More EStopConfig fixes

* Oops

---------

Co-authored-by: nullstalgia <[email protected]>
  • Loading branch information
hhvrc and nullstalgia authored Oct 3, 2024
1 parent 0a7e104 commit df27b6a
Show file tree
Hide file tree
Showing 43 changed files with 1,130 additions and 106 deletions.
1 change: 1 addition & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
[submodule "schemas"]
path = schemas
url = https://github.com/OpenShock/flatbuffers-schemas
branch = feature/estop-config
65 changes: 61 additions & 4 deletions frontend/src/lib/MessageHandlers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,15 @@ import { DeviceStateStore } from '$lib/stores';
import { SerializeWifiScanCommand } from '$lib/Serializers/WifiScanCommand';
import { toastDelegator } from '$lib/stores/ToastDelegator';
import { SetRfTxPinCommandResult } from '$lib/_fbs/open-shock/serialization/local/set-rf-tx-pin-command-result';
import { SetRfPinResultCode } from '$lib/_fbs/open-shock/serialization/local/set-rf-pin-result-code';
import { SetEstopPinCommandResult } from '$lib/_fbs/open-shock/serialization/local/set-estop-pin-command-result';
import { SetGPIOResultCode } from '$lib/_fbs/open-shock/serialization/local/set-gpioresult-code';
import { AccountLinkCommandResult } from '$lib/_fbs/open-shock/serialization/local/account-link-command-result';
import { AccountLinkResultCode } from '$lib/_fbs/open-shock/serialization/local/account-link-result-code';
import { ErrorMessage } from '$lib/_fbs/open-shock/serialization/local/error-message';
import { WifiNetworkEventHandler } from './WifiNetworkEventHandler';
import { mapConfig } from '$lib/mappers/ConfigMapper';
import { SetEstopEnabledCommand } from '$lib/_fbs/open-shock/serialization/local';
import { SetEstopEnabledCommandResult } from '$lib/_fbs/open-shock/serialization/local/set-estop-enabled-command-result';

export type MessageHandler = (wsClient: WebSocketClient, message: HubToLocalMessage) => void;

Expand Down Expand Up @@ -116,7 +119,7 @@ PayloadHandlers[HubToLocalMessagePayload.SetRfTxPinCommandResult] = (cli, msg) =

const result = payload.result();

if (result == SetRfPinResultCode.Success) {
if (result == SetGPIOResultCode.Success) {
DeviceStateStore.setRfTxPin(payload.pin());
toastDelegator.trigger({
message: 'Changed RF TX pin to: ' + payload.pin(),
Expand All @@ -125,10 +128,10 @@ PayloadHandlers[HubToLocalMessagePayload.SetRfTxPinCommandResult] = (cli, msg) =
} else {
let reason: string;
switch (result) {
case SetRfPinResultCode.InvalidPin:
case SetGPIOResultCode.InvalidPin:
reason = 'Invalid pin';
break;
case SetRfPinResultCode.InternalError:
case SetGPIOResultCode.InternalError:
reason = 'Internal error';
break;
default:
Expand All @@ -142,6 +145,60 @@ PayloadHandlers[HubToLocalMessagePayload.SetRfTxPinCommandResult] = (cli, msg) =
}
};

PayloadHandlers[HubToLocalMessagePayload.SetEstopEnabledCommandResult] = (cli, msg) => {
const payload = new SetEstopEnabledCommandResult();
msg.payload(payload);

const enabled = payload.enabled();
const success = payload.success();

if (success) {
DeviceStateStore.setEstopEnabled(payload.enabled());
toastDelegator.trigger({
message: 'Changed EStop enabled to: ' + enabled,
background: 'bg-green-500',
});
} else {
toastDelegator.trigger({
message: 'Failed to change EStop enabled',
background: 'bg-red-500',
});
}
};

PayloadHandlers[HubToLocalMessagePayload.SetEstopPinCommandResult] = (cli, msg) => {
const payload = new SetEstopPinCommandResult();
msg.payload(payload);

const result = payload.result();

if (result == SetGPIOResultCode.Success) {
const gpioPin = payload.gpioPin();
DeviceStateStore.setEstopGpioPin(gpioPin);
toastDelegator.trigger({
message: 'Changed EStop pin to: ' + gpioPin,
background: 'bg-green-500',
});
} else {
let reason: string;
switch (result) {
case SetGPIOResultCode.InvalidPin:
reason = 'Invalid pin';
break;
case SetGPIOResultCode.InternalError:
reason = 'Internal error';
break;
default:
reason = 'Unknown';
break;
}
toastDelegator.trigger({
message: 'Failed to change EStop pin: ' + reason,
background: 'bg-red-500',
});
}
};

export function WebSocketMessageBinaryHandler(cli: WebSocketClient, data: ArrayBuffer) {
const msg = HubToLocalMessage.getRootAsHubToLocalMessage(new ByteBuffer(new Uint8Array(data)));

Expand Down
16 changes: 16 additions & 0 deletions frontend/src/lib/Serializers/SetEstopEnabledCommand.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Builder as FlatbufferBuilder } from 'flatbuffers';
import { LocalToHubMessage } from '$lib/_fbs/open-shock/serialization/local/local-to-hub-message';
import { LocalToHubMessagePayload } from '$lib/_fbs/open-shock/serialization/local/local-to-hub-message-payload';
import { SetEstopEnabledCommand } from '$lib/_fbs/open-shock/serialization/local/set-estop-enabled-command';

export function SerializeSetEstopEnabledCommand(enabled: boolean): Uint8Array {
const fbb = new FlatbufferBuilder(64);

const cmdOffset = SetEstopEnabledCommand.createSetEstopEnabledCommand(fbb, enabled);

const payloadOffset = LocalToHubMessage.createLocalToHubMessage(fbb, LocalToHubMessagePayload.SetEstopEnabledCommand, cmdOffset);

fbb.finish(payloadOffset);

return fbb.asUint8Array();
}
16 changes: 16 additions & 0 deletions frontend/src/lib/Serializers/SetEstopPinCommand.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Builder as FlatbufferBuilder } from 'flatbuffers';
import { LocalToHubMessage } from '$lib/_fbs/open-shock/serialization/local/local-to-hub-message';
import { LocalToHubMessagePayload } from '$lib/_fbs/open-shock/serialization/local/local-to-hub-message-payload';
import { SetEstopPinCommand } from '$lib/_fbs/open-shock/serialization/local/set-estop-pin-command';

export function SerializeSetEstopPinCommand(pin: number): Uint8Array {
const fbb = new FlatbufferBuilder(64);

const cmdOffset = SetEstopPinCommand.createSetEstopPinCommand(fbb, pin);

const payloadOffset = LocalToHubMessage.createLocalToHubMessage(fbb, LocalToHubMessagePayload.SetEstopPinCommand, cmdOffset);

fbb.finish(payloadOffset);

return fbb.asUint8Array();
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

export { BackendConfig } from './configuration/backend-config';
export { CaptivePortalConfig } from './configuration/captive-portal-config';
export { EStopConfig } from './configuration/estop-config';
export { HubConfig } from './configuration/hub-config';
export { OtaUpdateChannel } from './configuration/ota-update-channel';
export { OtaUpdateConfig } from './configuration/ota-update-config';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// automatically generated by the FlatBuffers compiler, do not modify

/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */

import * as flatbuffers from 'flatbuffers';

export class EStopConfig {
bb: flatbuffers.ByteBuffer|null = null;
bb_pos = 0;
__init(i:number, bb:flatbuffers.ByteBuffer):EStopConfig {
this.bb_pos = i;
this.bb = bb;
return this;
}

static getRootAsEStopConfig(bb:flatbuffers.ByteBuffer, obj?:EStopConfig):EStopConfig {
return (obj || new EStopConfig()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
}

static getSizePrefixedRootAsEStopConfig(bb:flatbuffers.ByteBuffer, obj?:EStopConfig):EStopConfig {
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
return (obj || new EStopConfig()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
}

enabled():boolean {
const offset = this.bb!.__offset(this.bb_pos, 4);
return offset ? !!this.bb!.readInt8(this.bb_pos + offset) : false;
}

/**
* The GPIO pin connected to the E-Stop button
*/
gpioPin():number {
const offset = this.bb!.__offset(this.bb_pos, 6);
return offset ? this.bb!.readUint8(this.bb_pos + offset) : 0;
}

static startEStopConfig(builder:flatbuffers.Builder) {
builder.startObject(2);
}

static addEnabled(builder:flatbuffers.Builder, enabled:boolean) {
builder.addFieldInt8(0, +enabled, +false);
}

static addGpioPin(builder:flatbuffers.Builder, gpioPin:number) {
builder.addFieldInt8(1, gpioPin, 0);
}

static endEStopConfig(builder:flatbuffers.Builder):flatbuffers.Offset {
const offset = builder.endObject();
return offset;
}

static createEStopConfig(builder:flatbuffers.Builder, enabled:boolean, gpioPin:number):flatbuffers.Offset {
EStopConfig.startEStopConfig(builder);
EStopConfig.addEnabled(builder, enabled);
EStopConfig.addGpioPin(builder, gpioPin);
return EStopConfig.endEStopConfig(builder);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import * as flatbuffers from 'flatbuffers';

import { BackendConfig } from '../../../open-shock/serialization/configuration/backend-config';
import { CaptivePortalConfig } from '../../../open-shock/serialization/configuration/captive-portal-config';
import { EStopConfig } from '../../../open-shock/serialization/configuration/estop-config';
import { OtaUpdateConfig } from '../../../open-shock/serialization/configuration/ota-update-config';
import { RFConfig } from '../../../open-shock/serialization/configuration/rfconfig';
import { SerialInputConfig } from '../../../open-shock/serialization/configuration/serial-input-config';
Expand Down Expand Up @@ -78,8 +79,16 @@ otaUpdate(obj?:OtaUpdateConfig):OtaUpdateConfig|null {
return offset ? (obj || new OtaUpdateConfig()).__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : null;
}

/**
* E-Stop configuration
*/
estop(obj?:EStopConfig):EStopConfig|null {
const offset = this.bb!.__offset(this.bb_pos, 16);
return offset ? (obj || new EStopConfig()).__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : null;
}

static startHubConfig(builder:flatbuffers.Builder) {
builder.startObject(6);
builder.startObject(7);
}

static addRf(builder:flatbuffers.Builder, rfOffset:flatbuffers.Offset) {
Expand All @@ -106,6 +115,10 @@ static addOtaUpdate(builder:flatbuffers.Builder, otaUpdateOffset:flatbuffers.Off
builder.addFieldOffset(5, otaUpdateOffset, 0);
}

static addEstop(builder:flatbuffers.Builder, estopOffset:flatbuffers.Offset) {
builder.addFieldOffset(6, estopOffset, 0);
}

static endHubConfig(builder:flatbuffers.Builder):flatbuffers.Offset {
const offset = builder.endObject();
return offset;
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/lib/_fbs/open-shock/serialization/local.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ export { OtaUpdateSetIsEnabledCommand } from './local/ota-update-set-is-enabled-
export { OtaUpdateSetRequireManualApprovalCommand } from './local/ota-update-set-require-manual-approval-command';
export { OtaUpdateSetUpdateChannelCommand } from './local/ota-update-set-update-channel-command';
export { OtaUpdateStartUpdateCommand } from './local/ota-update-start-update-command';
export { SetEstopEnabledCommand } from './local/set-estop-enabled-command';
export { SetEstopPinCommand } from './local/set-estop-pin-command';
export { SetRfTxPinCommand } from './local/set-rf-tx-pin-command';
export { WifiNetworkConnectCommand } from './local/wifi-network-connect-command';
export { WifiNetworkDisconnectCommand } from './local/wifi-network-disconnect-command';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import { AccountLinkCommandResult } from '../../../open-shock/serialization/local/account-link-command-result';
import { ErrorMessage } from '../../../open-shock/serialization/local/error-message';
import { ReadyMessage } from '../../../open-shock/serialization/local/ready-message';
import { SetEstopEnabledCommandResult } from '../../../open-shock/serialization/local/set-estop-enabled-command-result';
import { SetEstopPinCommandResult } from '../../../open-shock/serialization/local/set-estop-pin-command-result';
import { SetRfTxPinCommandResult } from '../../../open-shock/serialization/local/set-rf-tx-pin-command-result';
import { WifiGotIpEvent } from '../../../open-shock/serialization/local/wifi-got-ip-event';
import { WifiLostIpEvent } from '../../../open-shock/serialization/local/wifi-lost-ip-event';
Expand All @@ -21,13 +23,15 @@ export enum HubToLocalMessagePayload {
WifiGotIpEvent = 5,
WifiLostIpEvent = 6,
AccountLinkCommandResult = 7,
SetRfTxPinCommandResult = 8
SetRfTxPinCommandResult = 8,
SetEstopEnabledCommandResult = 9,
SetEstopPinCommandResult = 10
}

export function unionToHubToLocalMessagePayload(
type: HubToLocalMessagePayload,
accessor: (obj:AccountLinkCommandResult|ErrorMessage|ReadyMessage|SetRfTxPinCommandResult|WifiGotIpEvent|WifiLostIpEvent|WifiNetworkEvent|WifiScanStatusMessage) => AccountLinkCommandResult|ErrorMessage|ReadyMessage|SetRfTxPinCommandResult|WifiGotIpEvent|WifiLostIpEvent|WifiNetworkEvent|WifiScanStatusMessage|null
): AccountLinkCommandResult|ErrorMessage|ReadyMessage|SetRfTxPinCommandResult|WifiGotIpEvent|WifiLostIpEvent|WifiNetworkEvent|WifiScanStatusMessage|null {
accessor: (obj:AccountLinkCommandResult|ErrorMessage|ReadyMessage|SetEstopEnabledCommandResult|SetEstopPinCommandResult|SetRfTxPinCommandResult|WifiGotIpEvent|WifiLostIpEvent|WifiNetworkEvent|WifiScanStatusMessage) => AccountLinkCommandResult|ErrorMessage|ReadyMessage|SetEstopEnabledCommandResult|SetEstopPinCommandResult|SetRfTxPinCommandResult|WifiGotIpEvent|WifiLostIpEvent|WifiNetworkEvent|WifiScanStatusMessage|null
): AccountLinkCommandResult|ErrorMessage|ReadyMessage|SetEstopEnabledCommandResult|SetEstopPinCommandResult|SetRfTxPinCommandResult|WifiGotIpEvent|WifiLostIpEvent|WifiNetworkEvent|WifiScanStatusMessage|null {
switch(HubToLocalMessagePayload[type]) {
case 'NONE': return null;
case 'ReadyMessage': return accessor(new ReadyMessage())! as ReadyMessage;
Expand All @@ -38,15 +42,17 @@ export function unionToHubToLocalMessagePayload(
case 'WifiLostIpEvent': return accessor(new WifiLostIpEvent())! as WifiLostIpEvent;
case 'AccountLinkCommandResult': return accessor(new AccountLinkCommandResult())! as AccountLinkCommandResult;
case 'SetRfTxPinCommandResult': return accessor(new SetRfTxPinCommandResult())! as SetRfTxPinCommandResult;
case 'SetEstopEnabledCommandResult': return accessor(new SetEstopEnabledCommandResult())! as SetEstopEnabledCommandResult;
case 'SetEstopPinCommandResult': return accessor(new SetEstopPinCommandResult())! as SetEstopPinCommandResult;
default: return null;
}
}

export function unionListToHubToLocalMessagePayload(
type: HubToLocalMessagePayload,
accessor: (index: number, obj:AccountLinkCommandResult|ErrorMessage|ReadyMessage|SetRfTxPinCommandResult|WifiGotIpEvent|WifiLostIpEvent|WifiNetworkEvent|WifiScanStatusMessage) => AccountLinkCommandResult|ErrorMessage|ReadyMessage|SetRfTxPinCommandResult|WifiGotIpEvent|WifiLostIpEvent|WifiNetworkEvent|WifiScanStatusMessage|null,
accessor: (index: number, obj:AccountLinkCommandResult|ErrorMessage|ReadyMessage|SetEstopEnabledCommandResult|SetEstopPinCommandResult|SetRfTxPinCommandResult|WifiGotIpEvent|WifiLostIpEvent|WifiNetworkEvent|WifiScanStatusMessage) => AccountLinkCommandResult|ErrorMessage|ReadyMessage|SetEstopEnabledCommandResult|SetEstopPinCommandResult|SetRfTxPinCommandResult|WifiGotIpEvent|WifiLostIpEvent|WifiNetworkEvent|WifiScanStatusMessage|null,
index: number
): AccountLinkCommandResult|ErrorMessage|ReadyMessage|SetRfTxPinCommandResult|WifiGotIpEvent|WifiLostIpEvent|WifiNetworkEvent|WifiScanStatusMessage|null {
): AccountLinkCommandResult|ErrorMessage|ReadyMessage|SetEstopEnabledCommandResult|SetEstopPinCommandResult|SetRfTxPinCommandResult|WifiGotIpEvent|WifiLostIpEvent|WifiNetworkEvent|WifiScanStatusMessage|null {
switch(HubToLocalMessagePayload[type]) {
case 'NONE': return null;
case 'ReadyMessage': return accessor(index, new ReadyMessage())! as ReadyMessage;
Expand All @@ -57,6 +63,8 @@ export function unionListToHubToLocalMessagePayload(
case 'WifiLostIpEvent': return accessor(index, new WifiLostIpEvent())! as WifiLostIpEvent;
case 'AccountLinkCommandResult': return accessor(index, new AccountLinkCommandResult())! as AccountLinkCommandResult;
case 'SetRfTxPinCommandResult': return accessor(index, new SetRfTxPinCommandResult())! as SetRfTxPinCommandResult;
case 'SetEstopEnabledCommandResult': return accessor(index, new SetEstopEnabledCommandResult())! as SetEstopEnabledCommandResult;
case 'SetEstopPinCommandResult': return accessor(index, new SetEstopPinCommandResult())! as SetEstopPinCommandResult;
default: return null;
}
}
Loading

1 comment on commit df27b6a

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cpp-Linter Report ⚠️

Some files did not pass the configured checks!

clang-format reports: 5 file(s) not formatted
  • include/serialization/_fbs/HubConfig_generated.h
  • include/serialization/_fbs/HubToLocalMessage_generated.h
  • include/serialization/_fbs/LocalToHubMessage_generated.h
  • src/CompatibilityChecks.cpp
  • src/config/EStopConfig.cpp

Have any feedback or feature suggestions? Share it here.

Please sign in to comment.