Skip to content

Commit

Permalink
[TEMP] a lot of stuff to properly commit
Browse files Browse the repository at this point in the history
  • Loading branch information
rafaellehmkuhl committed Oct 3, 2024
1 parent a64b49a commit 88cfb54
Show file tree
Hide file tree
Showing 7 changed files with 869 additions and 16 deletions.
6 changes: 6 additions & 0 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@ import { useAppInterfaceStore } from './stores/appInterface'
import { useMainVehicleStore } from './stores/mainVehicle'
import { useWidgetManagerStore } from './stores/widgetManager'
import { ConfigComponent } from './types/general'
import ConfigurationActionsView from './views/ConfigurationActionsView.vue'
import ConfigurationAlertsView from './views/ConfigurationAlertsView.vue'
import ConfigurationDevelopmentView from './views/ConfigurationDevelopmentView.vue'
import ConfigurationGeneralView from './views/ConfigurationGeneralView.vue'
Expand Down Expand Up @@ -410,6 +411,11 @@ const configMenu = [
title: 'Mission',
component: markRaw(ConfigurationMissionView) as ConfigComponent,
},
{
icon: 'mdi-run-fast',
title: 'Actions',
component: markRaw(ConfigurationActionsView) as ConfigComponent,
},
]
watch(
Expand Down
107 changes: 107 additions & 0 deletions src/libs/actions/data-lake.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/**
* A parameter for a Cockpit action
* @param { string } name - The name of the parameter
* @param { 'string' | 'number' | 'boolean' } type - The type of the parameter (string, number or boolean)
* @param { string } description - What the parameter does or means
* @param { string | number | boolean } defaultValue - The default value of the parameter
* @param { boolean } required - Whether the parameter is required or not
* @param { (string | number)[]? } options - The options for the parameter (only if type is string or number).
* @param { number? } min - The minimum value for the parameter (only if type is number).
* @param { number? } max - The maximum value for the parameter (only if type is number).
*/
class CockpitActionParameter {
id: string
name: string
type: 'string' | 'number' | 'boolean'
required: boolean
description?: string
defaultValue?: string | number | boolean
options?: (string | number)[]
min?: number
max?: number
// eslint-disable-next-line jsdoc/require-jsdoc
constructor(
id: string,
name: string,
type: 'string' | 'number' | 'boolean',
required: boolean,
description?: string,
defaultValue?: string | number | boolean,
options?: (string | number)[],
min?: number,
max?: number
) {
this.id = id
this.name = name
this.type = type
this.description = description
this.defaultValue = defaultValue
this.required = required
this.options = options
this.min = min
this.max = max
}
}

const cockpitActionParametersInfo: Record<string, CockpitActionParameter> = {}
export const cockpitActionParametersData: Record<string, string | number | boolean> = {}

export const getCockpitActionParametersInfo = (id: string): CockpitActionParameter | undefined => {
return cockpitActionParametersInfo[id]
}

export const getAllCockpitActionParametersInfo = (): Record<string, CockpitActionParameter> => {
return cockpitActionParametersInfo
}

export const getCockpitActionParameterInfo = (id: string): CockpitActionParameter | undefined => {
return cockpitActionParametersInfo[id]
}

export const setCockpitActionParameterInfo = (id: string, parameter: CockpitActionParameter): void => {
cockpitActionParametersInfo[id] = parameter
}

export const getCockpitActionParameterData = (id: string): string | number | boolean | undefined => {
return cockpitActionParametersData[id]
}

export const setCockpitActionParameterData = (id: string, data: string | number | boolean): void => {
cockpitActionParametersData[id] = data
}

const fakeRovNameInfo = new CockpitActionParameter(
'fakeRovName',
'Placeholder Parameter One',
'string',
true,
'This is a placeholder parameter for the first parameter'
)

const fakeRovAgeInitialDivesInfo = new CockpitActionParameter(
'fakeRovAgeInitialDives',
'Placeholder Parameter Two',
'number',
true,
'This is a placeholder parameter for the second parameter',
undefined,
undefined,
undefined,
0
)

const placeholderParameterThreeInfo = new CockpitActionParameter(
'placeholderParameterThree',
'Placeholder Parameter Three',
'boolean',
true,
'This is a placeholder parameter for the third parameter'
)

setCockpitActionParameterInfo(fakeRovNameInfo.id, fakeRovNameInfo)
setCockpitActionParameterInfo(fakeRovAgeInitialDivesInfo.id, fakeRovAgeInitialDivesInfo)
setCockpitActionParameterInfo(placeholderParameterThreeInfo.id, placeholderParameterThreeInfo)

setCockpitActionParameterData(fakeRovNameInfo.id, 'John Doe')
setCockpitActionParameterData(fakeRovAgeInitialDivesInfo.id, 5)
setCockpitActionParameterData(placeholderParameterThreeInfo.id, true)
150 changes: 150 additions & 0 deletions src/libs/actions/http-request.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import {
CockpitAction,
CockpitActionsFunction,
registerActionCallback,
registerNewAction,
} from '../joystick/protocols/cockpit-actions'
import { getCockpitActionParameterData } from './data-lake'

/**
* The types of HTTP methods that can be used.
*/
export enum HttpRequestMethod {
GET = 'GET',
POST = 'POST',
PUT = 'PUT',
DELETE = 'DELETE',
PATCH = 'PATCH',
}
export const availableHttpRequestMethods: HttpRequestMethod[] = Object.values(HttpRequestMethod)

export type HttpRequestActionConfig = {
/**
* The name of the action.
*/
name: string
/**
* The URL to send the request to.
*/
url: string
/**
* The HTTP method to use.
*/
method: HttpRequestMethod
/**
* The headers to send with the request.
*/
headers: Record<string, string>
/**
* The URL parameters to send with the request.
*/
urlParams: Record<string, string>
/**
* The body of the request.
*/
body: string
}

let registeredHttpRequestActionConfigs: Record<string, HttpRequestActionConfig> = {}

export const registerHttpRequestActionConfig = (action: HttpRequestActionConfig): void => {
const id = `http-request-action (${action.name})`
registeredHttpRequestActionConfigs[id] = action
saveHttpRequestActionConfigs()
updateCockpitActions()
}

export const getHttpRequestActionConfig = (id: string): HttpRequestActionConfig | undefined => {
return registeredHttpRequestActionConfigs[id]
}

export const getAllHttpRequestActionConfigs = (): Record<string, HttpRequestActionConfig> => {
return registeredHttpRequestActionConfigs
}

export const deleteHttpRequestActionConfig = (id: string): void => {
delete registeredHttpRequestActionConfigs[id]
saveHttpRequestActionConfigs()
updateCockpitActions()
}

export const updateHttpRequestActionConfig = (id: string, updatedAction: HttpRequestActionConfig): void => {
registeredHttpRequestActionConfigs[id] = updatedAction
saveHttpRequestActionConfigs()
updateCockpitActions()
}

export const updateCockpitActions = (): void => {
const httpResquestActions = getAllHttpRequestActionConfigs()
for (const [id, action] of Object.entries(httpResquestActions)) {
try {
const cockpitAction = new CockpitAction(id as CockpitActionsFunction, action.name)
registerNewAction(cockpitAction)
registerActionCallback(cockpitAction, getHttpRequestActionCallback(id))
} catch (error) {
console.error(`Error registering action ${id}: ${error}`)
}
}
}

export const loadHttpRequestActionConfigs = (): void => {
const savedActions = localStorage.getItem('cockpit-http-request-actions')
if (savedActions) {
registeredHttpRequestActionConfigs = JSON.parse(savedActions)
}
}

export const saveHttpRequestActionConfigs = (): void => {
localStorage.setItem('cockpit-http-request-actions', JSON.stringify(registeredHttpRequestActionConfigs))
}

export type HttpRequestActionCallback = () => void

export const getHttpRequestActionCallback = (id: string): HttpRequestActionCallback => {
const action = getHttpRequestActionConfig(id)
if (!action) {
throw new Error(`Action with id ${id} not found.`)
}

let parsedBody = action.body
const parsedUrlParams = action.urlParams

const cockpitInputsInBody = action.body.match(/{{\s*([^{}\s]+)\s*}}/g)
if (cockpitInputsInBody) {
for (const input of cockpitInputsInBody) {
const parsedInput = input.replace('{{', '').replace('}}', '').trim()
const inputData = getCockpitActionParameterData(parsedInput)
if (inputData) {
parsedBody = parsedBody.replace(input, inputData.toString())
}
}
}

const cockpitInputsInUrlParams = Object.entries(action.urlParams).filter(
([, value]) => typeof value === 'string' && value.startsWith('{{') && value.endsWith('}}')
)
if (cockpitInputsInUrlParams) {
for (const [key, value] of cockpitInputsInUrlParams) {
const parsedInput = value.replace('{{', '').replace('}}', '').trim()
const inputData = getCockpitActionParameterData(parsedInput)
if (inputData) {
parsedUrlParams[key] = inputData.toString()
}
}
}

const url = new URL(action.url)

url.search = new URLSearchParams(parsedUrlParams).toString()

return () => {
fetch(url, {
method: action.method,
headers: action.headers,
body: action.method === HttpRequestMethod.GET ? undefined : parsedBody,
})
}
}

loadHttpRequestActionConfigs()
updateCockpitActions()
21 changes: 11 additions & 10 deletions src/libs/joystick/protocols.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ import {
} from './protocols/mavlink-manual-control'
import { modifierKeyActions, otherAvailableActions } from './protocols/other'

export const allAvailableAxes: ProtocolAction[] = [
...Object.values(mavlinkManualControlAxes),
...Object.values(otherAvailableActions),
]
export const allAvailableAxes = (): ProtocolAction[] => {
return [...Object.values(mavlinkManualControlAxes), ...Object.values(otherAvailableActions)]
}

export const allAvailableButtons: ProtocolAction[] = [
...Object.values(availableCockpitActions),
...Object.values(availableMavlinkManualControlButtonFunctions),
...Object.values(otherAvailableActions),
...Object.values(modifierKeyActions),
]
export const allAvailableButtons = (): ProtocolAction[] => {
return [
...Object.values(availableCockpitActions),
...Object.values(availableMavlinkManualControlButtonFunctions),
...Object.values(otherAvailableActions),
...Object.values(modifierKeyActions),
]
}
16 changes: 12 additions & 4 deletions src/libs/joystick/protocols/cockpit-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export enum CockpitActionsFunction {
* An action to be performed by Cockpit itself
*/
export class CockpitAction implements ProtocolAction {
id: CockpitActionsFunction | string
id: CockpitActionsFunction
name: string
readonly protocol = JoystickProtocol.CockpitAction

Expand All @@ -34,8 +34,8 @@ export class CockpitAction implements ProtocolAction {
}
}

// Available actions
export const availableCockpitActions: { [key in CockpitActionsFunction | string]: CockpitAction } = {
// Predefined actions
export const predefinedCockpitActions: { [key in CockpitActionsFunction]: CockpitAction } = {
[CockpitActionsFunction.go_to_next_view]: new CockpitAction(CockpitActionsFunction.go_to_next_view, 'Go to next view'),
[CockpitActionsFunction.go_to_previous_view]: new CockpitAction(CockpitActionsFunction.go_to_previous_view, 'Go to previous view'),
[CockpitActionsFunction.toggle_full_screen]: new CockpitAction(CockpitActionsFunction.toggle_full_screen, 'Toggle full screen'),
Expand Down Expand Up @@ -68,10 +68,11 @@ interface CallbackEntry {
* Responsible for routing cockpit actions
*/
export class CockpitActionsManager {
availableActions: { [key in CockpitActionsFunction]: CockpitAction } = { ...predefinedCockpitActions }
actionsCallbacks: Record<string, CallbackEntry> = {}

registerNewAction = (action: CockpitAction): void => {
availableCockpitActions[action.id] = action
this.availableActions[action.id] = action
}

registerActionCallback = (action: CockpitAction, callback: CockpitActionCallback): string => {
Expand Down Expand Up @@ -101,6 +102,11 @@ export class CockpitActionsManager {

export const cockpitActionsManager = new CockpitActionsManager()

export const registerNewAction = (action: CockpitAction): void => {
cockpitActionsManager.registerNewAction(action)
console.debug(`Registered new action ${action.name} with id (${action.id}).`)
}

export const registerActionCallback = (action: CockpitAction, callback: CockpitActionCallback): string => {
return cockpitActionsManager.registerActionCallback(action, callback)
}
Expand All @@ -112,3 +118,5 @@ export const unregisterActionCallback = (id: string): void => {
export const executeActionCallback = (id: string): void => {
cockpitActionsManager.executeActionCallback(id)
}

export const availableCockpitActions = cockpitActionsManager.availableActions
9 changes: 7 additions & 2 deletions src/stores/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ export const useControllerStore = defineStore('controller', () => {
const protocolMappings = useBlueOsStorage(protocolMappingsKey, cockpitStandardToProtocols)
const protocolMappingIndex = useBlueOsStorage(protocolMappingIndexKey, 0)
const cockpitStdMappings = useBlueOsStorage(cockpitStdMappingsKey, availableGamepadToCockpitMaps)
const availableAxesActions = allAvailableAxes
const availableButtonActions = allAvailableButtons
const availableAxesActions = ref(allAvailableAxes())
const availableButtonActions = ref(allAvailableButtons())
const enableForwarding = ref(false)
const holdLastInputWhenWindowHidden = useBlueOsStorage('cockpit-hold-last-joystick-input-when-window-hidden', false)
const vehicleTypeProtocolMappingCorrespondency = useBlueOsStorage<typeof defaultProtocolMappingVehicleCorrespondency>(
Expand Down Expand Up @@ -400,6 +400,11 @@ export const useControllerStore = defineStore('controller', () => {
}
})

setInterval(() => {
availableButtonActions.value = allAvailableButtons()
availableAxesActions.value = allAvailableAxes()
}, 1000)

return {
registerControllerUpdateCallback,
enableForwarding,
Expand Down
Loading

0 comments on commit 88cfb54

Please sign in to comment.