Skip to content

Commit df27b6a

Browse files
hhvrcnullstalgia
andauthored
Allow setting/disabling Emergency Stop during setup/via Serial commands (#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]>
1 parent 0a7e104 commit df27b6a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1130
-106
lines changed

.gitmodules

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
[submodule "schemas"]
22
path = schemas
33
url = https://github.com/OpenShock/flatbuffers-schemas
4+
branch = feature/estop-config

frontend/src/lib/MessageHandlers/index.ts

Lines changed: 61 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,15 @@ import { DeviceStateStore } from '$lib/stores';
88
import { SerializeWifiScanCommand } from '$lib/Serializers/WifiScanCommand';
99
import { toastDelegator } from '$lib/stores/ToastDelegator';
1010
import { SetRfTxPinCommandResult } from '$lib/_fbs/open-shock/serialization/local/set-rf-tx-pin-command-result';
11-
import { SetRfPinResultCode } from '$lib/_fbs/open-shock/serialization/local/set-rf-pin-result-code';
11+
import { SetEstopPinCommandResult } from '$lib/_fbs/open-shock/serialization/local/set-estop-pin-command-result';
12+
import { SetGPIOResultCode } from '$lib/_fbs/open-shock/serialization/local/set-gpioresult-code';
1213
import { AccountLinkCommandResult } from '$lib/_fbs/open-shock/serialization/local/account-link-command-result';
1314
import { AccountLinkResultCode } from '$lib/_fbs/open-shock/serialization/local/account-link-result-code';
1415
import { ErrorMessage } from '$lib/_fbs/open-shock/serialization/local/error-message';
1516
import { WifiNetworkEventHandler } from './WifiNetworkEventHandler';
1617
import { mapConfig } from '$lib/mappers/ConfigMapper';
18+
import { SetEstopEnabledCommand } from '$lib/_fbs/open-shock/serialization/local';
19+
import { SetEstopEnabledCommandResult } from '$lib/_fbs/open-shock/serialization/local/set-estop-enabled-command-result';
1720

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

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

117120
const result = payload.result();
118121

119-
if (result == SetRfPinResultCode.Success) {
122+
if (result == SetGPIOResultCode.Success) {
120123
DeviceStateStore.setRfTxPin(payload.pin());
121124
toastDelegator.trigger({
122125
message: 'Changed RF TX pin to: ' + payload.pin(),
@@ -125,10 +128,10 @@ PayloadHandlers[HubToLocalMessagePayload.SetRfTxPinCommandResult] = (cli, msg) =
125128
} else {
126129
let reason: string;
127130
switch (result) {
128-
case SetRfPinResultCode.InvalidPin:
131+
case SetGPIOResultCode.InvalidPin:
129132
reason = 'Invalid pin';
130133
break;
131-
case SetRfPinResultCode.InternalError:
134+
case SetGPIOResultCode.InternalError:
132135
reason = 'Internal error';
133136
break;
134137
default:
@@ -142,6 +145,60 @@ PayloadHandlers[HubToLocalMessagePayload.SetRfTxPinCommandResult] = (cli, msg) =
142145
}
143146
};
144147

148+
PayloadHandlers[HubToLocalMessagePayload.SetEstopEnabledCommandResult] = (cli, msg) => {
149+
const payload = new SetEstopEnabledCommandResult();
150+
msg.payload(payload);
151+
152+
const enabled = payload.enabled();
153+
const success = payload.success();
154+
155+
if (success) {
156+
DeviceStateStore.setEstopEnabled(payload.enabled());
157+
toastDelegator.trigger({
158+
message: 'Changed EStop enabled to: ' + enabled,
159+
background: 'bg-green-500',
160+
});
161+
} else {
162+
toastDelegator.trigger({
163+
message: 'Failed to change EStop enabled',
164+
background: 'bg-red-500',
165+
});
166+
}
167+
};
168+
169+
PayloadHandlers[HubToLocalMessagePayload.SetEstopPinCommandResult] = (cli, msg) => {
170+
const payload = new SetEstopPinCommandResult();
171+
msg.payload(payload);
172+
173+
const result = payload.result();
174+
175+
if (result == SetGPIOResultCode.Success) {
176+
const gpioPin = payload.gpioPin();
177+
DeviceStateStore.setEstopGpioPin(gpioPin);
178+
toastDelegator.trigger({
179+
message: 'Changed EStop pin to: ' + gpioPin,
180+
background: 'bg-green-500',
181+
});
182+
} else {
183+
let reason: string;
184+
switch (result) {
185+
case SetGPIOResultCode.InvalidPin:
186+
reason = 'Invalid pin';
187+
break;
188+
case SetGPIOResultCode.InternalError:
189+
reason = 'Internal error';
190+
break;
191+
default:
192+
reason = 'Unknown';
193+
break;
194+
}
195+
toastDelegator.trigger({
196+
message: 'Failed to change EStop pin: ' + reason,
197+
background: 'bg-red-500',
198+
});
199+
}
200+
};
201+
145202
export function WebSocketMessageBinaryHandler(cli: WebSocketClient, data: ArrayBuffer) {
146203
const msg = HubToLocalMessage.getRootAsHubToLocalMessage(new ByteBuffer(new Uint8Array(data)));
147204

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { Builder as FlatbufferBuilder } from 'flatbuffers';
2+
import { LocalToHubMessage } from '$lib/_fbs/open-shock/serialization/local/local-to-hub-message';
3+
import { LocalToHubMessagePayload } from '$lib/_fbs/open-shock/serialization/local/local-to-hub-message-payload';
4+
import { SetEstopEnabledCommand } from '$lib/_fbs/open-shock/serialization/local/set-estop-enabled-command';
5+
6+
export function SerializeSetEstopEnabledCommand(enabled: boolean): Uint8Array {
7+
const fbb = new FlatbufferBuilder(64);
8+
9+
const cmdOffset = SetEstopEnabledCommand.createSetEstopEnabledCommand(fbb, enabled);
10+
11+
const payloadOffset = LocalToHubMessage.createLocalToHubMessage(fbb, LocalToHubMessagePayload.SetEstopEnabledCommand, cmdOffset);
12+
13+
fbb.finish(payloadOffset);
14+
15+
return fbb.asUint8Array();
16+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { Builder as FlatbufferBuilder } from 'flatbuffers';
2+
import { LocalToHubMessage } from '$lib/_fbs/open-shock/serialization/local/local-to-hub-message';
3+
import { LocalToHubMessagePayload } from '$lib/_fbs/open-shock/serialization/local/local-to-hub-message-payload';
4+
import { SetEstopPinCommand } from '$lib/_fbs/open-shock/serialization/local/set-estop-pin-command';
5+
6+
export function SerializeSetEstopPinCommand(pin: number): Uint8Array {
7+
const fbb = new FlatbufferBuilder(64);
8+
9+
const cmdOffset = SetEstopPinCommand.createSetEstopPinCommand(fbb, pin);
10+
11+
const payloadOffset = LocalToHubMessage.createLocalToHubMessage(fbb, LocalToHubMessagePayload.SetEstopPinCommand, cmdOffset);
12+
13+
fbb.finish(payloadOffset);
14+
15+
return fbb.asUint8Array();
16+
}

frontend/src/lib/_fbs/open-shock/serialization/configuration.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
export { BackendConfig } from './configuration/backend-config';
66
export { CaptivePortalConfig } from './configuration/captive-portal-config';
7+
export { EStopConfig } from './configuration/estop-config';
78
export { HubConfig } from './configuration/hub-config';
89
export { OtaUpdateChannel } from './configuration/ota-update-channel';
910
export { OtaUpdateConfig } from './configuration/ota-update-config';
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// automatically generated by the FlatBuffers compiler, do not modify
2+
3+
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
4+
5+
import * as flatbuffers from 'flatbuffers';
6+
7+
export class EStopConfig {
8+
bb: flatbuffers.ByteBuffer|null = null;
9+
bb_pos = 0;
10+
__init(i:number, bb:flatbuffers.ByteBuffer):EStopConfig {
11+
this.bb_pos = i;
12+
this.bb = bb;
13+
return this;
14+
}
15+
16+
static getRootAsEStopConfig(bb:flatbuffers.ByteBuffer, obj?:EStopConfig):EStopConfig {
17+
return (obj || new EStopConfig()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
18+
}
19+
20+
static getSizePrefixedRootAsEStopConfig(bb:flatbuffers.ByteBuffer, obj?:EStopConfig):EStopConfig {
21+
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
22+
return (obj || new EStopConfig()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
23+
}
24+
25+
enabled():boolean {
26+
const offset = this.bb!.__offset(this.bb_pos, 4);
27+
return offset ? !!this.bb!.readInt8(this.bb_pos + offset) : false;
28+
}
29+
30+
/**
31+
* The GPIO pin connected to the E-Stop button
32+
*/
33+
gpioPin():number {
34+
const offset = this.bb!.__offset(this.bb_pos, 6);
35+
return offset ? this.bb!.readUint8(this.bb_pos + offset) : 0;
36+
}
37+
38+
static startEStopConfig(builder:flatbuffers.Builder) {
39+
builder.startObject(2);
40+
}
41+
42+
static addEnabled(builder:flatbuffers.Builder, enabled:boolean) {
43+
builder.addFieldInt8(0, +enabled, +false);
44+
}
45+
46+
static addGpioPin(builder:flatbuffers.Builder, gpioPin:number) {
47+
builder.addFieldInt8(1, gpioPin, 0);
48+
}
49+
50+
static endEStopConfig(builder:flatbuffers.Builder):flatbuffers.Offset {
51+
const offset = builder.endObject();
52+
return offset;
53+
}
54+
55+
static createEStopConfig(builder:flatbuffers.Builder, enabled:boolean, gpioPin:number):flatbuffers.Offset {
56+
EStopConfig.startEStopConfig(builder);
57+
EStopConfig.addEnabled(builder, enabled);
58+
EStopConfig.addGpioPin(builder, gpioPin);
59+
return EStopConfig.endEStopConfig(builder);
60+
}
61+
}

frontend/src/lib/_fbs/open-shock/serialization/configuration/hub-config.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import * as flatbuffers from 'flatbuffers';
66

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

82+
/**
83+
* E-Stop configuration
84+
*/
85+
estop(obj?:EStopConfig):EStopConfig|null {
86+
const offset = this.bb!.__offset(this.bb_pos, 16);
87+
return offset ? (obj || new EStopConfig()).__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : null;
88+
}
89+
8190
static startHubConfig(builder:flatbuffers.Builder) {
82-
builder.startObject(6);
91+
builder.startObject(7);
8392
}
8493

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

118+
static addEstop(builder:flatbuffers.Builder, estopOffset:flatbuffers.Offset) {
119+
builder.addFieldOffset(6, estopOffset, 0);
120+
}
121+
109122
static endHubConfig(builder:flatbuffers.Builder):flatbuffers.Offset {
110123
const offset = builder.endObject();
111124
return offset;

frontend/src/lib/_fbs/open-shock/serialization/local.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ export { OtaUpdateSetIsEnabledCommand } from './local/ota-update-set-is-enabled-
1515
export { OtaUpdateSetRequireManualApprovalCommand } from './local/ota-update-set-require-manual-approval-command';
1616
export { OtaUpdateSetUpdateChannelCommand } from './local/ota-update-set-update-channel-command';
1717
export { OtaUpdateStartUpdateCommand } from './local/ota-update-start-update-command';
18+
export { SetEstopEnabledCommand } from './local/set-estop-enabled-command';
19+
export { SetEstopPinCommand } from './local/set-estop-pin-command';
1820
export { SetRfTxPinCommand } from './local/set-rf-tx-pin-command';
1921
export { WifiNetworkConnectCommand } from './local/wifi-network-connect-command';
2022
export { WifiNetworkDisconnectCommand } from './local/wifi-network-disconnect-command';

frontend/src/lib/_fbs/open-shock/serialization/local/hub-to-local-message-payload.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import { AccountLinkCommandResult } from '../../../open-shock/serialization/local/account-link-command-result';
66
import { ErrorMessage } from '../../../open-shock/serialization/local/error-message';
77
import { ReadyMessage } from '../../../open-shock/serialization/local/ready-message';
8+
import { SetEstopEnabledCommandResult } from '../../../open-shock/serialization/local/set-estop-enabled-command-result';
9+
import { SetEstopPinCommandResult } from '../../../open-shock/serialization/local/set-estop-pin-command-result';
810
import { SetRfTxPinCommandResult } from '../../../open-shock/serialization/local/set-rf-tx-pin-command-result';
911
import { WifiGotIpEvent } from '../../../open-shock/serialization/local/wifi-got-ip-event';
1012
import { WifiLostIpEvent } from '../../../open-shock/serialization/local/wifi-lost-ip-event';
@@ -21,13 +23,15 @@ export enum HubToLocalMessagePayload {
2123
WifiGotIpEvent = 5,
2224
WifiLostIpEvent = 6,
2325
AccountLinkCommandResult = 7,
24-
SetRfTxPinCommandResult = 8
26+
SetRfTxPinCommandResult = 8,
27+
SetEstopEnabledCommandResult = 9,
28+
SetEstopPinCommandResult = 10
2529
}
2630

2731
export function unionToHubToLocalMessagePayload(
2832
type: HubToLocalMessagePayload,
29-
accessor: (obj:AccountLinkCommandResult|ErrorMessage|ReadyMessage|SetRfTxPinCommandResult|WifiGotIpEvent|WifiLostIpEvent|WifiNetworkEvent|WifiScanStatusMessage) => AccountLinkCommandResult|ErrorMessage|ReadyMessage|SetRfTxPinCommandResult|WifiGotIpEvent|WifiLostIpEvent|WifiNetworkEvent|WifiScanStatusMessage|null
30-
): AccountLinkCommandResult|ErrorMessage|ReadyMessage|SetRfTxPinCommandResult|WifiGotIpEvent|WifiLostIpEvent|WifiNetworkEvent|WifiScanStatusMessage|null {
33+
accessor: (obj:AccountLinkCommandResult|ErrorMessage|ReadyMessage|SetEstopEnabledCommandResult|SetEstopPinCommandResult|SetRfTxPinCommandResult|WifiGotIpEvent|WifiLostIpEvent|WifiNetworkEvent|WifiScanStatusMessage) => AccountLinkCommandResult|ErrorMessage|ReadyMessage|SetEstopEnabledCommandResult|SetEstopPinCommandResult|SetRfTxPinCommandResult|WifiGotIpEvent|WifiLostIpEvent|WifiNetworkEvent|WifiScanStatusMessage|null
34+
): AccountLinkCommandResult|ErrorMessage|ReadyMessage|SetEstopEnabledCommandResult|SetEstopPinCommandResult|SetRfTxPinCommandResult|WifiGotIpEvent|WifiLostIpEvent|WifiNetworkEvent|WifiScanStatusMessage|null {
3135
switch(HubToLocalMessagePayload[type]) {
3236
case 'NONE': return null;
3337
case 'ReadyMessage': return accessor(new ReadyMessage())! as ReadyMessage;
@@ -38,15 +42,17 @@ export function unionToHubToLocalMessagePayload(
3842
case 'WifiLostIpEvent': return accessor(new WifiLostIpEvent())! as WifiLostIpEvent;
3943
case 'AccountLinkCommandResult': return accessor(new AccountLinkCommandResult())! as AccountLinkCommandResult;
4044
case 'SetRfTxPinCommandResult': return accessor(new SetRfTxPinCommandResult())! as SetRfTxPinCommandResult;
45+
case 'SetEstopEnabledCommandResult': return accessor(new SetEstopEnabledCommandResult())! as SetEstopEnabledCommandResult;
46+
case 'SetEstopPinCommandResult': return accessor(new SetEstopPinCommandResult())! as SetEstopPinCommandResult;
4147
default: return null;
4248
}
4349
}
4450

4551
export function unionListToHubToLocalMessagePayload(
4652
type: HubToLocalMessagePayload,
47-
accessor: (index: number, obj:AccountLinkCommandResult|ErrorMessage|ReadyMessage|SetRfTxPinCommandResult|WifiGotIpEvent|WifiLostIpEvent|WifiNetworkEvent|WifiScanStatusMessage) => AccountLinkCommandResult|ErrorMessage|ReadyMessage|SetRfTxPinCommandResult|WifiGotIpEvent|WifiLostIpEvent|WifiNetworkEvent|WifiScanStatusMessage|null,
53+
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,
4854
index: number
49-
): AccountLinkCommandResult|ErrorMessage|ReadyMessage|SetRfTxPinCommandResult|WifiGotIpEvent|WifiLostIpEvent|WifiNetworkEvent|WifiScanStatusMessage|null {
55+
): AccountLinkCommandResult|ErrorMessage|ReadyMessage|SetEstopEnabledCommandResult|SetEstopPinCommandResult|SetRfTxPinCommandResult|WifiGotIpEvent|WifiLostIpEvent|WifiNetworkEvent|WifiScanStatusMessage|null {
5056
switch(HubToLocalMessagePayload[type]) {
5157
case 'NONE': return null;
5258
case 'ReadyMessage': return accessor(index, new ReadyMessage())! as ReadyMessage;
@@ -57,6 +63,8 @@ export function unionListToHubToLocalMessagePayload(
5763
case 'WifiLostIpEvent': return accessor(index, new WifiLostIpEvent())! as WifiLostIpEvent;
5864
case 'AccountLinkCommandResult': return accessor(index, new AccountLinkCommandResult())! as AccountLinkCommandResult;
5965
case 'SetRfTxPinCommandResult': return accessor(index, new SetRfTxPinCommandResult())! as SetRfTxPinCommandResult;
66+
case 'SetEstopEnabledCommandResult': return accessor(index, new SetEstopEnabledCommandResult())! as SetEstopEnabledCommandResult;
67+
case 'SetEstopPinCommandResult': return accessor(index, new SetEstopPinCommandResult())! as SetEstopPinCommandResult;
6068
default: return null;
6169
}
6270
}

0 commit comments

Comments
 (0)