diff --git a/README.md b/README.md index 50eb5e9..e698462 100644 --- a/README.md +++ b/README.md @@ -50,3 +50,46 @@ The application listed below is required: ### Command Logs - Command logs are shown in "CmdLog" page. + +### Functions available to use for *.ops file +- Command + + Four types of Command are available for OBC: `RT`, `TL`, `UTL`, `BL` +- Comment + + Comment function is available by prefixing a line with `#`. +- Other Functions + + `call`: You can call other *.ops file. + + ex.) `call TEST.ops`. + + `wait_sec`: You can specify how many seconds to wait before moving to the next file line. + + ex.) `wait_sec 2` + + `let`: You can define internal variables. + + The right-hand side of the `let` function can perform four arithmetic operations and other operations (*1). + + The current telemetry value or an already defined variable using `let` function can be assigned by enclosing it in braces `{}`. + + ex.1)`let testA = 10 + 60 * 10` + + ex.2) `let testB = {testA} + 10 * Math.sin(Math.PI)` + + `get`: You can get the current value of the telemerty or the defined variable. + + ex.) `get testA` + + `check_value`: You can check whether a specific value fulfills the requirement. + + `check_value` function is basically used as follows: + + `check_value A == B` + + `check_value A >= B` + + Currently, `A` is limited to telemetry names and variables defined by `let` function. + + `B` can be any value, the names of telemetry, or variables already defined using `let` function. + + The names of telemetry, or variables already defined must be enclosed in braces {}. + + `wait_until`: 条件式が成立するまで待機する機能. + + `wait_until` function is basically used as follows: + + `wait_until A == B` + + `wait_until A >= B` + + Currently, `A` is limited to telemetry names and variables defined by `let` function. + + `B` can be any value, the names of telemetry, or variables already defined using `let` function. + + The names of telemetry, or variables already defined must be enclosed in braces {}. + +- Annotation(*1):About other operations + + The following is a list of operations that can be used in addition to the four basic arithmetic operations: + + [Math Object](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Math) + + Javascript provides built-in objects that allow the following operations: + + ex.) + + `Math.PI` + + `Math.abs(x)` + + `Math.asin(x)` + + `Math.acos(x)` + + `Math.hypot(x, y, z, ...)` diff --git a/aspnetapp/WINGS/ClientApp/src/components/command/plan_display/PlanTabPanel.tsx b/aspnetapp/WINGS/ClientApp/src/components/command/plan_display/PlanTabPanel.tsx index 166b974..84196fc 100644 --- a/aspnetapp/WINGS/ClientApp/src/components/command/plan_display/PlanTabPanel.tsx +++ b/aspnetapp/WINGS/ClientApp/src/components/command/plan_display/PlanTabPanel.tsx @@ -7,10 +7,10 @@ import TableCell from '@material-ui/core/TableCell'; import TableContainer from '@material-ui/core/TableContainer'; import TableHead from '@material-ui/core/TableHead'; import TableRow from '@material-ui/core/TableRow'; -import { CommandPlanLine, RequestStatus } from '../../../models'; +import { CommandPlanLine, RequestStatus, CmdFileVariable } from '../../../models'; import RequestTableRow from './RequestTableRow'; -import { selectedPlanRowAction, execRequestSuccessAction, execRequestErrorAction, execRequestsStartAction, execRequestsEndAction } from '../../../redux/plans/actions'; -import { getActivePlanId, getAllIndexes, getInExecution, getPlanContents, getSelectedRow } from '../../../redux/plans/selectors'; +import { selectedPlanRowAction, execRequestSuccessAction, execRequestErrorAction, execRequestsStartAction, execRequestsEndAction, cmdFileVariableEditAction } from '../../../redux/plans/actions'; +import { getActivePlanId, getAllIndexes, getInExecution, getPlanContents, getSelectedRow, getCommandFileVariables } from '../../../redux/plans/selectors'; import { useDispatch, useSelector } from 'react-redux'; import { openPlan, postCommand, postCommandFileLineLog } from '../../../redux/plans/operations'; import { RootState } from '../../../redux/store/RootState'; @@ -74,6 +74,7 @@ const PlanTabPanel = (props: PlanTabPanelProps) => { const [showModal, setShowModal] = React.useState(false); const [text, setText] = React.useState(""); const [num, setNum] = React.useState(0); + const [cmdFileVariables, setCmdFileVariables] = React.useState(getCommandFileVariables(selector)); let selectedRow = getSelectedRow(selector); @@ -98,6 +99,12 @@ const PlanTabPanel = (props: PlanTabPanelProps) => { const container = document.getElementById('plan-table-container'); const tbody = document.getElementById('plan-table-body'); + interface GetVariable { + value: string | number, + isSuccess: boolean, + convType: string + } + const advanceSelectedRow = (nextRow: number) => { selectedRow < content.length-1 && dispatch(selectedPlanRowAction(nextRow)); if (container && tbody && tbody.getElementsByTagName('tr')[0] != undefined) { @@ -187,6 +194,25 @@ const PlanTabPanel = (props: PlanTabPanelProps) => { setShowModal(false); } + const setCmdline = async (row: number, cmdlineText: string) => { + // do things like LoadCommandFileAsync + const res = await fetch(`/api/operations/${opid}/cmd_plans/0/${activePlanId}/${row}`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({text: cmdlineText}) + }); + const json = await res.json(); + if (res.status === 200) { + const commandFileLine = json.data; + dispatch(finishEditCommandLineAction(row, commandFileLine)); + } else { + const message = `Status Code: ${res.status}\n${json.message ? json.message: "unknown error"}`; + dispatch(openErrorDialogAction(message)); + } + } + const executeMultipleRequests = async () => { let row = selectedRow; do { @@ -203,6 +229,93 @@ const PlanTabPanel = (props: PlanTabPanelProps) => { } } + const getVariableValue = (variableName: string) => { + let variableIndex = -1; + let outcome: GetVariable = { value: NaN, isSuccess: false, convType: "" }; + if (variableName.toLowerCase() == "unixtime_now") { + outcome.value = Math.floor(new Date().getTime() / 1000); + outcome.isSuccess = true; + } else if (cmdFileVariables.findIndex(index => index.variable === variableName) >= 0) { + variableIndex = cmdFileVariables.findIndex(index => index.variable === variableName); + outcome.value = cmdFileVariables[variableIndex].value; + outcome.isSuccess = true; + } else if (variableName.indexOf('.') > -1) { + var tlms = getLatestTelemetries(selector)[variableName.split('.')[0]]; + if (tlms.findIndex(index => index.telemetryInfo.name === variableName) >= 0) { + variableIndex = tlms.findIndex(index => index.telemetryInfo.name === variableName); + } else if (tlms.findIndex(index => index.telemetryInfo.name === variableName.split('.').slice(1).join('.')) >= 0) { + variableIndex = tlms.findIndex(index => index.telemetryInfo.name === variableName.split('.').slice(1).join('.')); + } else { + return outcome; + } + outcome.value = parseTlmValue(tlms[variableIndex].telemetryValue.value, tlms[variableIndex].telemetryInfo.convType); + outcome.isSuccess = true; + outcome.convType = tlms[variableIndex].telemetryInfo.convType; + } + return outcome; + } + + const compareValue = (compare: string, variable: GetVariable, refValue: string) => { + let comparedValue = (refValue.indexOf("{") == -1) ? refValue + : getVariableValue(refValue.substring(refValue.indexOf("{") + 1, refValue.indexOf("}"))).value.toString(); + switch (compare) { + case "==": + if (variable.value === parseTlmValue(comparedValue, variable.convType)) { + return true; + } else { + return false; + } + case ">=": + if (variable.value >= parseTlmValue(comparedValue, variable.convType)) { + return true; + } else { + return false; + } + case "<=": + if (variable.value <= parseTlmValue(comparedValue, variable.convType)) { + return true; + } else { + return false; + } + case ">": + if (variable.value > parseTlmValue(comparedValue, variable.convType)) { + return true; + } else { + return false; + } + case "<": + if (variable.value < parseTlmValue(comparedValue, variable.convType)) { + return true; + } else { + return false; + } + case "!=": + if (variable.value !== parseTlmValue(comparedValue, variable.convType)) { + return true; + } else { + return false; + } + case "in": + while (refValue.indexOf("{") != -1) { + let cmdFileVar = refValue.substring(refValue.indexOf("{") + 1, refValue.indexOf("}")); + let varValue = getVariableValue(cmdFileVar); + if (!varValue.isSuccess) { + return false; + } + refValue = refValue.replace("{" + cmdFileVar + "}", varValue.value.toString()); + } + let valueLower = parseTlmValue(refValue.substring(refValue.indexOf("[") + 1, refValue.indexOf(",")), variable.convType); + let valueUpper = parseTlmValue(refValue.substring(refValue.indexOf(",") + 1, refValue.indexOf("]")), variable.convType); + if (variable.value >= valueLower && variable.value <= valueUpper) { + return true; + } else { + return false; + } + default: + return false; + } + } + const executeRequest = async (row: number): Promise => { const req = content[row].request; let exeret = false; @@ -214,7 +327,52 @@ const PlanTabPanel = (props: PlanTabPanelProps) => { case "command": let commandret = [false]; - await dispatch(postCommand(row, req, commandret)); + let paramsValue = []; + + if (req.body.execTimeStr == null) { + req.body.execTimeStr = ""; + } + else if (req.body.execTimeStr.indexOf("{") != -1) { + let varTi = req.body.execTimeStr.substring(req.body.execTimeStr.indexOf("{") + 1, + req.body.execTimeStr.indexOf("}")); + let tiValue = getVariableValue(varTi); + + if (!tiValue.isSuccess) { + dispatch(execRequestErrorAction(row)); + return false; + } + + if (req.body.execType == "TL" || req.body.execType == "BL") { + req.body.execTimeInt = tiValue.value; + } else if (req.body.execType == "UTL") { + req.body.execTimeDouble = tiValue.value; + } else { + dispatch(execRequestErrorAction(row)); + return false; + } + } + + if (req.body.params.length != 0) { + for (let i = 0; i < req.body.params.length; i++) { + if (req.body.params[i].value.indexOf("{") != -1) { + let varStart = req.body.params[i].value.indexOf("{") + 1; + let varEnd = req.body.params[i].value.indexOf("}"); + let varParam = req.body.params[i].value.substring(varStart, varEnd); + let varValue = getVariableValue(varParam); + + if (!varValue.isSuccess) { + dispatch(execRequestErrorAction(row)); + return false; + } else { + paramsValue.push(varValue.value.toString()); + } + + } else { + paramsValue.push(req.body.params[i].value); + } + } + } + await dispatch(postCommand(row, req, paramsValue, commandret)); exeret = commandret[0]; break; @@ -252,81 +410,85 @@ const PlanTabPanel = (props: PlanTabPanelProps) => { } break; - case "check_value": - const tlms = getLatestTelemetries(selector)[req.body.variable.split('.')[0]]; - var tlmidx = -1; - if (tlms.findIndex(index => index.telemetryInfo.name === req.body.variable) >= 0) { - tlmidx = tlms.findIndex(index => index.telemetryInfo.name === req.body.variable); - } else if (tlms.findIndex(index => index.telemetryInfo.name === req.body.variable.split('.').slice(1).join('.')) >= 0) { - tlmidx = tlms.findIndex(index => index.telemetryInfo.name === req.body.variable.split('.').slice(1).join('.')); + case "wait_until": + var timer = 0; + var timeoutsec = (req.body.timeoutsec == "" || isNaN(req.body.timeoutsec)) ? 10 : Number(req.body.timeoutsec); + while (!reqret && timer < timeoutsec) { + let latestTlmValue = getVariableValue(req.body.variable); + if (!latestTlmValue.isSuccess) { + break; + } + + if(compareValue(req.body.compare, latestTlmValue, req.body.value)) { + reqret = true; + } else { + await _sleep(1000); + timer += 1; + } + } + if (reqret) { + dispatch(execRequestSuccessAction(row)); } else { + dispatch(execRequestErrorAction(row)); + } + break; + + case "check_value": + let tlmValue = getVariableValue(req.body.variable); + if (!tlmValue.isSuccess) { break; } - const tlm = tlms[tlmidx]; - const tlmValue = parseTlmValue(tlm.telemetryValue.value, tlm.telemetryInfo.convType); - const comparedValue = parseTlmValue(req.body.value, tlm.telemetryInfo.convType); - switch (req.body.compare) { - case "==": - if (tlmValue === comparedValue) { - dispatch(execRequestSuccessAction(row)); - reqret = true; - } else { - dispatch(execRequestErrorAction(row)); - reqret = false; - } - break; - case ">=": - if (tlmValue >= comparedValue) { - dispatch(execRequestSuccessAction(row)); - reqret = true; - } else { - dispatch(execRequestErrorAction(row)); - reqret = false; - } - break; - case "<=": - if (tlmValue <= comparedValue) { - dispatch(execRequestSuccessAction(row)); - reqret = true; - } else { - dispatch(execRequestErrorAction(row)); - reqret = false; - } - break; - case ">": - if (tlmValue > comparedValue) { - dispatch(execRequestSuccessAction(row)); - reqret = true; - } else { - dispatch(execRequestErrorAction(row)); - reqret = false; - } - break; - case "<": - if (tlmValue < comparedValue) { - dispatch(execRequestSuccessAction(row)); - reqret = true; - } else { - dispatch(execRequestErrorAction(row)); - reqret = false; - } - break; - case "!=": - if (tlmValue !== comparedValue) { - dispatch(execRequestSuccessAction(row)); - reqret = true; - } else { - dispatch(execRequestErrorAction(row)); - reqret = false; - } - break; - default: + + if (compareValue(req.body.compare, tlmValue, req.body.value)) { + dispatch(execRequestSuccessAction(row)); + reqret = true; + } else { + dispatch(execRequestErrorAction(row)); + reqret = false; + } + break; + + case "let": + var equ = req.body.equation; + // const innerVar = tlms[tlmidx]; + // const val = parseTlmValue(innerVar.telemetryValue.value, innerVar.telemetryInfo.convType); + reqret = true; + while (equ.indexOf("{") != -1) { + let cmdFileVar = equ.substring(equ.indexOf("{") + 1, equ.indexOf("}")); + let varValue = getVariableValue(cmdFileVar); + if (!varValue.isSuccess) { dispatch(execRequestErrorAction(row)); - reqret = false; - break; + return false; + } + equ = equ.replace("{" + cmdFileVar + "}", varValue.value.toString()); + } + let equAns; + try { + equAns = eval(equ); + } + catch (e) { + equAns = equ; + } + var cmdFileVariablesTemp = cmdFileVariables; + if (cmdFileVariables.findIndex(index => index.variable === req.body.variable) >= 0) { + var varIndex = cmdFileVariables.findIndex(index => index.variable === req.body.variable) + cmdFileVariablesTemp[varIndex].value = equAns; + } else { + cmdFileVariablesTemp.push({variable: req.body.variable, value: equAns}); } + setCmdFileVariables(cmdFileVariablesTemp); + dispatch(execRequestSuccessAction(row)); + dispatch(cmdFileVariableEditAction(cmdFileVariablesTemp)); + break; + + case "get": + let reqValue = getVariableValue(req.body.variable).value; + let newText = (req.stopFlag ? "." : " ") + `${req.method} ${req.body.variable} ${reqValue}`; + setCmdline(row, newText); + dispatch(execRequestSuccessAction(row)); + reqret = true; break; - + default: break; } diff --git a/aspnetapp/WINGS/ClientApp/src/components/command/plan_display/RequestTableRow.tsx b/aspnetapp/WINGS/ClientApp/src/components/command/plan_display/RequestTableRow.tsx index 9adc66e..81ad47f 100644 --- a/aspnetapp/WINGS/ClientApp/src/components/command/plan_display/RequestTableRow.tsx +++ b/aspnetapp/WINGS/ClientApp/src/components/command/plan_display/RequestTableRow.tsx @@ -73,7 +73,7 @@ const RequestTableRow = (props: RequestTableRowProps) => { const showCommandParam = (command: Command) => { return ( <> - {command.execType !== "RT" && (<>{spacer}{command.execTime})} + {command.execType !== "RT" && (<>{spacer}{command.execTimeStr})} {command.params.length > 0 && ( command.params.map((param,i) => ( @@ -92,11 +92,20 @@ const RequestTableRow = (props: RequestTableRowProps) => { case "wait_sec": return <>{body.time} + case "wait_until": + return <>{body.variable}{spacer}{body.compare}{spacer}{body.value}{spacer}{body.statement}{spacer}{body.timeoutsec} + case "call": return <>{body.fileName} case "check_value": return <>{body.variable}{spacer}{body.compare}{spacer}{body.value} + + case "let": + return <>{body.variable}{spacer}{body.equal}{spacer}{body.equation} + + case "get": + return <>{body.variable}{spacer}{body.value} default: return; diff --git a/aspnetapp/WINGS/ClientApp/src/components/command/plan_edit/CommandSelectArea.tsx b/aspnetapp/WINGS/ClientApp/src/components/command/plan_edit/CommandSelectArea.tsx index 7f67a61..11fb163 100644 --- a/aspnetapp/WINGS/ClientApp/src/components/command/plan_edit/CommandSelectArea.tsx +++ b/aspnetapp/WINGS/ClientApp/src/components/command/plan_edit/CommandSelectArea.tsx @@ -77,7 +77,9 @@ const CommandSelectionArea = () => { const newSelectedCommand = { ...command, execType: execType, - execTime: NaN + execTimeInt: NaN, + execTimeDouble: NaN, + execTimeStr: "" }; dispatch(selectedCommandEditAction(newSelectedCommand)); }; @@ -92,7 +94,9 @@ const CommandSelectionArea = () => { const newSelectedCommand = { ...commands[index], execType: command.execType, - execTime: command.execTime, + execTimeInt: command.execTimeInt, + execTimeDouble: command.execTimeDouble, + execTimeStr: command.execTimeStr, isViaMobc: command.isViaMobc } dispatch(selectedCommandEditAction(newSelectedCommand)); diff --git a/aspnetapp/WINGS/ClientApp/src/components/command/plan_edit/SetParamTable.tsx b/aspnetapp/WINGS/ClientApp/src/components/command/plan_edit/SetParamTable.tsx index 1a98ad3..cc13755 100644 --- a/aspnetapp/WINGS/ClientApp/src/components/command/plan_edit/SetParamTable.tsx +++ b/aspnetapp/WINGS/ClientApp/src/components/command/plan_edit/SetParamTable.tsx @@ -44,15 +44,88 @@ const SetParamTable = (props: SetParamAreaProps) => { const classes = useStyles(); const dispatch = useDispatch(); const { command } = props; + const [execTime, setExecTime] = React.useState(); + const [execType, setExecType] = React.useState(); + + if (command.execType != execType) + { + if (command.execType == "RT") + { + const newSelectedCommand = { + ...command, + execTimeInt: 0, + execTimeDouble: 0, + execTimeStr: "" + } + setExecTime('0'); + setExecType(command.execType); + dispatch(selectedCommandEditAction(newSelectedCommand)); + } + else if (command.execType == 'TL' || command.execType == 'BL') + { + var execTimeInt = (execTime==undefined)?'0':execTime; + const newSelectedCommand = { + ...command, + execTimeInt: parseInt(execTimeInt), + execTimeDouble: 0, + execTimeStr: execTimeInt + } + setExecTime('0'); + setExecTime(isNaN(parseInt(execTimeInt))?'0':String(parseInt(execTimeInt))); + setExecType(command.execType); + dispatch(selectedCommandEditAction(newSelectedCommand)); + } + else if (command.execType == 'UTL') + { + var execTimeDouble = (execTime==undefined)?'0':execTime; + if (execTimeDouble.slice(-1) !== '.') + { + const newSelectedCommand = { + ...command, + execTimeInt: 0, + execTimeDouble: parseFloat(execTimeDouble), + execTimeStr: execTimeDouble + } + setExecTime(isNaN(parseFloat(execTimeDouble))?'0':String(parseFloat(execTimeDouble))); + dispatch(selectedCommandEditAction(newSelectedCommand)); + } + else if (execTimeDouble.slice(-2) !== '.') + { + setExecTime(execTimeDouble); + } + setExecType(command.execType); + } + } const handleExecTimeChange = (event: any) => { const newSelectedCommand = { ...command, - execTime: parseInt(event.target.value) + execTimeInt: parseInt(event.target.value), + execTimeDouble: 0, + execTimeStr: event.target.value.toString() } + setExecTime(isNaN(parseInt(event.target.value))?'0':String(parseInt(event.target.value))); dispatch(selectedCommandEditAction(newSelectedCommand)); }; + const handleExecUnixTimeChange = (event: any) => { + if (event.target.value.slice(-1) !== '.') + { + const newSelectedCommand = { + ...command, + execTimeInt: 0, + execTimeDouble: parseFloat(event.target.value), + execTimeStr: event.target.value.toString() + } + setExecTime(isNaN(parseFloat(event.target.value))?'0':String(parseFloat(event.target.value))); + dispatch(selectedCommandEditAction(newSelectedCommand)); + } + else if (event.target.value.indexOf('.') == event.target.value.length-1) + { + setExecTime(event.target.value); + } + }; + const handleParamValueChange = (event: any, i: number) => { const newSelectedCommand = { ...command, @@ -85,13 +158,13 @@ const SetParamTable = (props: SetParamAreaProps) => { - {(command.execType === "TL" || command.execType === "BL" || command.execType === "UTL") && ( + {(command.execType === "TL" || command.execType === "BL") && ( Time @@ -99,6 +172,20 @@ const SetParamTable = (props: SetParamAreaProps) => { TI )} + {(command.execType === "UTL") && ( + + Time + + + + int32_t + UnixTime + + )} {command.params.length > 0 && ( command.params.map((param,i) => diff --git a/aspnetapp/WINGS/ClientApp/src/models/Command.ts b/aspnetapp/WINGS/ClientApp/src/models/Command.ts index a1574c0..f0df7c4 100644 --- a/aspnetapp/WINGS/ClientApp/src/models/Command.ts +++ b/aspnetapp/WINGS/ClientApp/src/models/Command.ts @@ -9,7 +9,9 @@ export type CommandParam = { export type Command = { component: string, execType: string, - execTime: number, + execTimeInt: number, + execTimeDouble: number, + execTimeStr: string, name: string, code: string, target: string, diff --git a/aspnetapp/WINGS/ClientApp/src/models/CommandPlan.ts b/aspnetapp/WINGS/ClientApp/src/models/CommandPlan.ts index 3f27c6e..c4b5a33 100644 --- a/aspnetapp/WINGS/ClientApp/src/models/CommandPlan.ts +++ b/aspnetapp/WINGS/ClientApp/src/models/CommandPlan.ts @@ -28,6 +28,7 @@ export type CommandPlanLine = { export type CommandPlanState = { allIndexes: CommandPlanIndex[], + cmdFileVariables: CmdFileVariable[]; openedIds: string[], activeId: string, selectedRow: number, @@ -41,3 +42,8 @@ export type CommandPlanState = { }, inExecution: boolean } + +export type CmdFileVariable = { + variable: string, + value: string | number +} diff --git a/aspnetapp/WINGS/ClientApp/src/redux/plans/actions.ts b/aspnetapp/WINGS/ClientApp/src/redux/plans/actions.ts index 5dd4330..e41a1ec 100644 --- a/aspnetapp/WINGS/ClientApp/src/redux/plans/actions.ts +++ b/aspnetapp/WINGS/ClientApp/src/redux/plans/actions.ts @@ -1,9 +1,10 @@ -import { Command, CommandPlanLine, FileIndex, Request } from "../../models"; +import { Command, CommandPlanLine, FileIndex, Request, CmdFileVariable } from "../../models"; export const FETCH_PLAN_INDEXES = 'FETCH_PLAN_INDEXES' as const; export const OPEN_PLAN = 'OPEN_PLAN' as const; export const CLOSE_PLAN = 'CLOSE_PLAN' as const; export const ACTIVATE_PLAN = 'ACTIVATE_PLAN' as const; +export const CMDFILE_VARIABLE_EDIT = 'CMDFILE_VARIABLE_EDIT' as const; export const SELECT_PLAN_ROW = 'SELECT_PLAN_ROW' as const; export const EXEC_REQUEST_SUCCESS = 'EXEC_REQUEST_SUCCESS' as const; export const EXEC_REQUEST_ERROR = 'EXEC_REQUEST_ERROR' as const; @@ -50,6 +51,13 @@ export const activatePlanAction = (id: string) => { }; }; +export const cmdFileVariableEditAction = (cmdFileVariables: CmdFileVariable[]) => { + return { + type: CMDFILE_VARIABLE_EDIT, + payload: cmdFileVariables + } +} + export const selectedPlanRowAction = (row: number) => { return { type: SELECT_PLAN_ROW, diff --git a/aspnetapp/WINGS/ClientApp/src/redux/plans/operations.ts b/aspnetapp/WINGS/ClientApp/src/redux/plans/operations.ts index 87314a5..649fbcc 100644 --- a/aspnetapp/WINGS/ClientApp/src/redux/plans/operations.ts +++ b/aspnetapp/WINGS/ClientApp/src/redux/plans/operations.ts @@ -24,14 +24,20 @@ export const openPlan = (id: string) => { } }; -export const postCommand = (row: number, req: Request, ret: boolean[]) => { +export const postCommand = (row: number, req: Request, paramsValue: string[], ret: boolean[]) => { return async (dispatch: Dispatch, getState: () => RootState) => { const opid = getState().operation.id; + var body = JSON.parse(JSON.stringify(req.body)); + if (paramsValue.length != 0) { + for (var i = 0; i < paramsValue.length; i++) { + body.params[i].value = paramsValue[i]; + } + } const res = await fetch(`/api/operations/${opid}/cmd`,{ method: 'POST', headers: { 'Content-Type': 'application/json' - }, body: JSON.stringify({ command : req.body }) + }, body: JSON.stringify({ command : body }) }); const json = await res.json(); if (res.status === 200 && json.ack) { diff --git a/aspnetapp/WINGS/ClientApp/src/redux/plans/reducers.ts b/aspnetapp/WINGS/ClientApp/src/redux/plans/reducers.ts index 86e85cf..3d3b57c 100644 --- a/aspnetapp/WINGS/ClientApp/src/redux/plans/reducers.ts +++ b/aspnetapp/WINGS/ClientApp/src/redux/plans/reducers.ts @@ -9,6 +9,7 @@ type Actions = | ReturnType | ReturnType | ReturnType + | ReturnType | ReturnType | ReturnType | ReturnType @@ -89,6 +90,13 @@ export const PlansReducer = (state = initialState.plans, action: Actions) => { selectedRow: -1 } } + + case Actions.CMDFILE_VARIABLE_EDIT: { + return { + ...state, + cmdFileVariables: action.payload + } + } case Actions.SELECT_PLAN_ROW: { return { diff --git a/aspnetapp/WINGS/ClientApp/src/redux/plans/selectors.ts b/aspnetapp/WINGS/ClientApp/src/redux/plans/selectors.ts index 7a52c32..e51960a 100644 --- a/aspnetapp/WINGS/ClientApp/src/redux/plans/selectors.ts +++ b/aspnetapp/WINGS/ClientApp/src/redux/plans/selectors.ts @@ -34,6 +34,11 @@ export const getSelectedRow = createSelector( state => state.selectedRow ); +export const getCommandFileVariables = createSelector( + [plansSelector], + state => state.cmdFileVariables +) + export const getSelectedCommand = createSelector( [plansSelector], state => state.selectedCommand diff --git a/aspnetapp/WINGS/ClientApp/src/redux/store/initialState.ts b/aspnetapp/WINGS/ClientApp/src/redux/store/initialState.ts index 7477e59..269cc56 100644 --- a/aspnetapp/WINGS/ClientApp/src/redux/store/initialState.ts +++ b/aspnetapp/WINGS/ClientApp/src/redux/store/initialState.ts @@ -58,6 +58,7 @@ const initialState: RootState = { filePath: "", cmdFileInfoIndex: "" }], + cmdFileVariables: [], openedIds: [UNPLANNED_ID], activeId: UNPLANNED_ID, selectedRow: -1, @@ -70,7 +71,9 @@ const initialState: RootState = { command: { component: "", execType: "RT", - execTime: 0, + execTimeInt: 0, + execTimeDouble: 0, + execTimeStr: "", name: "", code: "", target: "", diff --git a/aspnetapp/WINGS/Data/CommandDbRepository.cs b/aspnetapp/WINGS/Data/CommandDbRepository.cs index 760b834..a24a52b 100644 --- a/aspnetapp/WINGS/Data/CommandDbRepository.cs +++ b/aspnetapp/WINGS/Data/CommandDbRepository.cs @@ -86,7 +86,8 @@ private async Task> LoadFileAsync(TlmCmdFileLocation location, Tlm { Component = ComponentName, ExecType = CmdExecType.RT, - ExecTime = 0, + ExecTimeInt = 0, + ExecTimeDouble = 0, Name = cols[1], Code = cols[3], Target = cols[2], diff --git a/aspnetapp/WINGS/Data/CommandFileLogRepository.cs b/aspnetapp/WINGS/Data/CommandFileLogRepository.cs index 63efdcd..5478518 100644 --- a/aspnetapp/WINGS/Data/CommandFileLogRepository.cs +++ b/aspnetapp/WINGS/Data/CommandFileLogRepository.cs @@ -118,13 +118,13 @@ private string CommandFileLineToText(CommandFileLine command_file_line_log) sb.Append("RT." + cmd_tmp.Name); break; case CmdExecType.TL: - sb.Append("TL." + cmd_tmp.Name + " " + cmd_tmp.ExecTime); + sb.Append("TL." + cmd_tmp.Name + " " + cmd_tmp.ExecTimeStr); break; case CmdExecType.BL: - sb.Append("BL." + cmd_tmp.Name + " " + cmd_tmp.ExecTime); + sb.Append("BL." + cmd_tmp.Name + " " + cmd_tmp.ExecTimeStr); break; case CmdExecType.UTL: - sb.Append("UTL." + cmd_tmp.Name + " " + cmd_tmp.ExecTime); + sb.Append("UTL." + cmd_tmp.Name + " " + cmd_tmp.ExecTimeStr); break; default: return ""; @@ -144,12 +144,22 @@ private string CommandFileLineToText(CommandFileLine command_file_line_log) case "wait_sec": sb.Append(command_file_line_log.Method + " " + command_file_line_log.Body.GetProperty("time").ToString()); break; + case "wait_until": + sb.Append(command_file_line_log.Method + " " + command_file_line_log.Body.GetProperty("variable").ToString() + " " + command_file_line_log.Body.GetProperty("compare").ToString() + " " + command_file_line_log.Body.GetProperty("value").ToString() + + " " + command_file_line_log.Body.GetProperty("statement").ToString() + " " + command_file_line_log.Body.GetProperty("timeoutsec").ToString()); + break; case "call": sb.Append(command_file_line_log.Method + " " + command_file_line_log.Body.GetProperty("fileName").ToString()); break; case "check_value": sb.Append(command_file_line_log.Method + " " + command_file_line_log.Body.GetProperty("variable").ToString() + " " + command_file_line_log.Body.GetProperty("compare").ToString() + " " + command_file_line_log.Body.GetProperty("value").ToString()); break; + case "let": + sb.Append(command_file_line_log.Method + " " + command_file_line_log.Body.GetProperty("variable").ToString() + " " + command_file_line_log.Body.GetProperty("equal").ToString() + " " + command_file_line_log.Body.GetProperty("equation").ToString()); + break; + case "get": + sb.Append(command_file_line_log.Method + " " + command_file_line_log.Body.GetProperty("variable").ToString() + " " + command_file_line_log.Body.GetProperty("value").ToString()); + break; } if (!String.IsNullOrEmpty(command_file_line_log.InlineComment)) { diff --git a/aspnetapp/WINGS/Data/CommandFileRepository.cs b/aspnetapp/WINGS/Data/CommandFileRepository.cs index 3865ab4..23b8f93 100644 --- a/aspnetapp/WINGS/Data/CommandFileRepository.cs +++ b/aspnetapp/WINGS/Data/CommandFileRepository.cs @@ -252,12 +252,30 @@ private void ControlCheck(ref string line, CommandFileLine newContent) splitlinelist.RemoveAt(0); WaitsecParse(splitlinelist, newContent); break; + case "wait_until": + newContent.Type = "control"; + newContent.Method = splitlinelist[0].ToLower(); + splitlinelist.RemoveAt(0); + WaituntilParse(splitlinelist, newContent); + break; case "check_value": newContent.Type = "control"; newContent.Method = splitlinelist[0].ToLower(); splitlinelist.RemoveAt(0); CheckValueParse(splitlinelist, newContent); break; + case "let": + newContent.Type = "control"; + newContent.Method = splitlinelist[0].ToLower(); + splitlinelist.RemoveAt(0); + LetParse(splitlinelist, newContent); + break; + case "get": + newContent.Type = "control"; + newContent.Method = splitlinelist[0].ToLower(); + splitlinelist.RemoveAt(0); + GetParse(splitlinelist, newContent); + break; } } @@ -335,6 +353,77 @@ private void WaitsecParse(List splitlinelist, CommandFileLine newContent } } + private void WaituntilParse(List splitlinelist, CommandFileLine newContent) + { + switch (splitlinelist.Count) + { + case 3: + if (splitlinelist[1] == "==" || splitlinelist[1] == "<=" || splitlinelist[1] == ">=" || splitlinelist[1] == "<" || splitlinelist[1] == ">" || splitlinelist[1] == "!=") + { + newContent.Body = new + { + variable = splitlinelist[0], + compare = splitlinelist[1], + value = splitlinelist[2] + }; + } + else if (splitlinelist[1] == "in" && splitlinelist[2].Contains("[") && splitlinelist[2].Contains("]")) + { + newContent.Body = new + { + variable = splitlinelist[0], + compare = splitlinelist[1], + value = splitlinelist[2], + statement = "", + timeoutsec = "" + }; + } + else + { + newContent.SyntaxError = true; + newContent.ErrorMessage = "Method \"wait_until\" : wrong number of data"; + } + break; + default: + if ((splitlinelist[1] == "==" || splitlinelist[1] == "<=" || splitlinelist[1] == ">=" || splitlinelist[1] == "<" || splitlinelist[1] == ">" || splitlinelist[1] == "!=") + && splitlinelist[3].Contains("-timeoutsec") && splitlinelist.Count == 5) + { + newContent.Body = new + { + variable = splitlinelist[0], + compare = splitlinelist[1], + value = splitlinelist[2], + statement = splitlinelist[3], + timeoutsec = splitlinelist[4] + }; + } + else if (splitlinelist[1] == "in" && splitlinelist[2].Contains("[") && splitlinelist[splitlinelist.Count - 3].Contains("]") && splitlinelist[splitlinelist.Count - 2].Contains("-timeoutsec")) + { + var valueRange = splitlinelist[2]; + for(int i = 3; i < splitlinelist.Count; i++) + { + valueRange += " " + splitlinelist[i]; + } + + newContent.Body = new + { + variable = splitlinelist[0], + compare = splitlinelist[1], + value = valueRange, + statement = splitlinelist[splitlinelist.Count - 2], + timeoutsec = splitlinelist[splitlinelist.Count - 1] + }; + + } + else + { + newContent.SyntaxError = true; + newContent.ErrorMessage = "Method \"wait_until\" : wrong number of data"; + } + break; + } + } + private void CheckValueParse(List splitlinelist, CommandFileLine newContent) { switch (splitlinelist.Count) @@ -349,15 +438,89 @@ private void CheckValueParse(List splitlinelist, CommandFileLine newCont value = splitlinelist[2] }; } + else if (splitlinelist[1] == "in" && splitlinelist[1].Contains("[") && splitlinelist[1].Contains("]")) + { + newContent.Body = new + { + variable = splitlinelist[0], + compare = splitlinelist[1], + value = splitlinelist[2] + }; + } else { newContent.SyntaxError = true; newContent.ErrorMessage = "Method \"check_value\" : wrong number of data"; } break; + default: + if (splitlinelist[1] == "in" && splitlinelist[2].Contains("[") && splitlinelist[splitlinelist.Count - 1].Contains("]")) + { + var valueRange = splitlinelist[2]; + for(int i = 3; i < splitlinelist.Count; i++) + { + valueRange += " " + splitlinelist[i]; + } + + newContent.Body = new + { + variable = splitlinelist[0], + compare = splitlinelist[1], + value = valueRange + }; + } + else + { + newContent.SyntaxError = true; + newContent.ErrorMessage = "Method \"check_value\" : wrong number of data"; + } + break; + } + } + + private void LetParse(List splitlinelist, CommandFileLine newContent) + { + if(splitlinelist.Count >= 3 && splitlinelist[1] == "=") + { + var equation = splitlinelist[2]; + if (splitlinelist.Count >= 4) { + for (int i = 3; i < splitlinelist.Count; i++) { + equation += " " + splitlinelist[i]; + } + } + newContent.Body = new + { + variable = splitlinelist[0], + equal = splitlinelist[1], + equation = equation + }; + } else { + newContent.SyntaxError = true; + newContent.ErrorMessage = "Method \"let\" : wrong number of data"; + } + } + + private void GetParse(List splitlinelist, CommandFileLine newContent) + { + switch (splitlinelist.Count) + { + case 1: + newContent.Body = new + { + variable = splitlinelist[0], + value = "" + }; + break; + case 2: + newContent.Body = new + { + variable = splitlinelist[0], + value = splitlinelist[1] + }; + break; default: newContent.SyntaxError = true; - newContent.ErrorMessage = "Method \"check_value\" : wrong number of data"; + newContent.ErrorMessage = "Method \"get\" : wrong number of data"; break; } } @@ -387,18 +550,24 @@ private void CommandExeParse(List splitlinelist, CommandFileLine newCont var isViaMobc = false; if (dotIndex > 3) { - var mobcIndex = splitlinelist[0].IndexOf("MOBC_"); - if (mobcIndex >= 0 && dotIndex > 11) + if (splitlinelist[0].Contains("MOBC_")) { - var afterMobcLine = splitlinelist[0].Substring(mobcIndex + 8); - component = afterMobcLine.Substring(0, afterMobcLine.IndexOf('_')); - Enum.TryParse(splitlinelist[0].Substring(mobcIndex + 5, dotIndex - mobcIndex - 5), out execType); - isViaMobc = true; + var cmdLayer = splitlinelist[0].Split("."); + if (cmdLayer.Length >= 3 && (cmdLayer[1].Contains("AOBC_") || cmdLayer[1].Contains("TOBC_"))) { + component = cmdLayer[1].Substring(0, cmdLayer[0].IndexOf('_')); + dotIndex += (cmdLayer[1].Length + 1); + isViaMobc = true; + } + else { + component = cmdLayer[0].Substring(0, cmdLayer[0].IndexOf('_')); + } + Enum.TryParse(cmdLayer[0].Substring(cmdLayer[0].IndexOf('_') + 1), out execType); } else { - component = splitlinelist[0].Substring(0, splitlinelist[0].IndexOf('_')); - Enum.TryParse(splitlinelist[0].Substring(5, dotIndex - 5), out execType); + var componentLine = splitlinelist[0].Substring(0, dotIndex); + component = splitlinelist[0].Substring(0, componentLine.IndexOf('_')); + Enum.TryParse(componentLine.Substring(componentLine.IndexOf('_') + 1), out execType); } } var cmdBodyBuf = commandDb.FirstOrDefault(c => c.Name == splitlinelist[0].Substring(dotIndex + 1) && c.Component == component); @@ -413,17 +582,40 @@ private void CommandExeParse(List splitlinelist, CommandFileLine newCont newContent.Body.ExecType = execType; newContent.Type = "command"; splitlinelist.RemoveAt(0); - if (newContent.Body.ExecType == CmdExecType.TL || newContent.Body.ExecType == CmdExecType.BL || newContent.Body.ExecType == CmdExecType.UTL) + if (newContent.Body.ExecType == CmdExecType.TL || newContent.Body.ExecType == CmdExecType.BL) { - uint execTime; - if (uint.TryParse(splitlinelist[0], out execTime)) + uint execTimeInt; + if (splitlinelist[0].Contains("{")) { + newContent.Body.ExecTimeStr = splitlinelist[0]; + } + else if (uint.TryParse(splitlinelist[0], out execTimeInt)) { - newContent.Body.ExecTime = execTime; + newContent.Body.ExecTimeInt = execTimeInt; + newContent.Body.ExecTimeStr = splitlinelist[0]; } else { newContent.SyntaxError = true; - newContent.ErrorMessage = "\"CommandExe\" : Exetype is 'TL' or 'BL' or 'UTL'. The first parameter should be uint."; + newContent.ErrorMessage = "\"CommandExe\" : Exetype is 'TL' or 'BL'. The first parameter should be uint."; + return; + } + splitlinelist.RemoveAt(0); + } + else if (newContent.Body.ExecType == CmdExecType.UTL) + { + double execTimeDouble; + if (splitlinelist[0].Contains("{")) { + newContent.Body.ExecTimeStr = splitlinelist[0]; + } + else if (double.TryParse(splitlinelist[0], out execTimeDouble)) + { + newContent.Body.ExecTimeDouble = execTimeDouble; + newContent.Body.ExecTimeStr = splitlinelist[0]; + } + else + { + newContent.SyntaxError = true; + newContent.ErrorMessage = "\"CommandExe\" : Exetype is 'UTL'. The first parameter should be double."; return; } splitlinelist.RemoveAt(0); @@ -471,10 +663,15 @@ private void ParamsTypeCheck(List splitlinelist, CommandFileLine newCont } for (int SL = 0; SL < newContent.Body.Params.Count; SL++) { - if (splitlinelist[SL].Contains("0x")) + if (splitlinelist[SL].Contains("{")) + { + newContent.Body.Params[SL].Value = splitlinelist[SL]; + continue; + } + else if (splitlinelist[SL].Contains("0x")) { style = NumberStyles.HexNumber; - splitlinelist[SL] = splitlinelist[SL].Replace("0x", ""); //TryParseは0xがあると成功しない + splitlinelist[SL] = splitlinelist[SL].Replace("0x", ""); } else { diff --git a/aspnetapp/WINGS/Migrations/ApplicationDbContextModelSnapshot.cs b/aspnetapp/WINGS/Migrations/ApplicationDbContextModelSnapshot.cs index 1306955..9855c71 100644 --- a/aspnetapp/WINGS/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/aspnetapp/WINGS/Migrations/ApplicationDbContextModelSnapshot.cs @@ -30,8 +30,11 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("CmdName") .HasColumnType("varchar(255)"); - b.Property("ExecTime") + b.Property("ExecTimeInt") .HasColumnType("int unsigned"); + + b.Property("ExecTimeDouble") + .HasColumnType("double"); b.Property("ExecType") .IsRequired() diff --git a/aspnetapp/WINGS/Models/Command.cs b/aspnetapp/WINGS/Models/Command.cs index 2def7a7..8e2c867 100644 --- a/aspnetapp/WINGS/Models/Command.cs +++ b/aspnetapp/WINGS/Models/Command.cs @@ -15,7 +15,9 @@ public class Command { public string Component { get; set; } public CmdExecType ExecType { get; set; } - public uint ExecTime { get; set; } + public uint ExecTimeInt { get; set; } + public double ExecTimeDouble { get; set; } + public string ExecTimeStr {get; set; } public string Name { get; set; } public string Code { get; set; } public string Target { get; set; } diff --git a/aspnetapp/WINGS/Models/CommandLog.cs b/aspnetapp/WINGS/Models/CommandLog.cs index a120027..ae05535 100644 --- a/aspnetapp/WINGS/Models/CommandLog.cs +++ b/aspnetapp/WINGS/Models/CommandLog.cs @@ -11,8 +11,9 @@ public class CommandLog [Column(TypeName = "varchar(64)")] public CmdExecType ExecType { get; set; } - public uint ExecTime { get; set; } - + public uint ExecTimeInt { get; set; } + public double ExecTimeDouble { get; set; } + [Column(TypeName = "varchar(255)")] public string CmdName { get; set; } diff --git a/aspnetapp/WINGS/Services/Core/CommandService.cs b/aspnetapp/WINGS/Services/Core/CommandService.cs index 130a65c..c3752b3 100644 --- a/aspnetapp/WINGS/Services/Core/CommandService.cs +++ b/aspnetapp/WINGS/Services/Core/CommandService.cs @@ -247,7 +247,8 @@ private CommandLog CommandToLog(string opid, Command command) return new CommandLog { ExecType = command.ExecType, - ExecTime = command.ExecTime, + ExecTimeInt = command.ExecTimeInt, + ExecTimeDouble = command.ExecTimeDouble, SentAt = DateTime.Now, CmdName = command.Name, OperationId = opid, diff --git a/aspnetapp/WINGS/Services/TMTC/Processor/UserDefined/MOBC/MobcTcPacketGenerator.cs b/aspnetapp/WINGS/Services/TMTC/Processor/UserDefined/MOBC/MobcTcPacketGenerator.cs index 47c67f5..23a65b3 100644 --- a/aspnetapp/WINGS/Services/TMTC/Processor/UserDefined/MOBC/MobcTcPacketGenerator.cs +++ b/aspnetapp/WINGS/Services/TMTC/Processor/UserDefined/MOBC/MobcTcPacketGenerator.cs @@ -65,7 +65,6 @@ protected override byte[] GeneratePacket(Command command) var channelId = GetChannelId(command); var exeType = GetExeType(command); var apid = GetApid(command); - var ti = GetTi(command); //TC Transfer Frame (except CRC) SetTctfVer(packet, TctfVer.Ver1); @@ -95,7 +94,7 @@ protected override byte[] GeneratePacket(Command command) SetUdCmdType(packet, UdCmdType.Sm); SetUdChannelId(packet, channelId); SetUdExeType(packet, exeType); - SetUdTi(packet, ti, exeType); + SetUdTi(packet, exeType, command); SetParams(packet, command.Params, UserDataPos + UserDataHdrLen); //CRC @@ -203,9 +202,14 @@ private TcpApid GetApid(Command command) return TcpApid.MobcCmd; } } - private uint GetTi(Command command) + protected uint GetTi(Command command) { - return command.ExecTime; + return command.ExecTimeInt; + } + + protected double GetUnixTi(Command command) + { + return command.ExecTimeDouble; } private void SetTctfVer(byte[] packet, TctfVer ver) @@ -391,16 +395,17 @@ private void SetUdExeType(byte[] packet, UdExeType type) int pos = UserDataPos + 3; packet[pos] = (byte)type; } - private void SetUdTi(byte[] packet, uint ti, UdExeType type) + private void SetUdTi(byte[] packet, UdExeType type, Command command) { int pos = UserDataPos + 4; if(type == UdExeType.UnixTimeline || type == UdExeType.AobcUnixTimeline || type == UdExeType.TobcUnixTimeline) { - uint epoch_unix_time = 1577836800; // UNIX TIME of 2020/1/1 00:00:00(UTC) + double epoch_unix_time = 1577836800; // UNIX TIME of 2020/1/1 00:00:00(UTC) uint converted_unix_time = 0; - if (ti - epoch_unix_time > 0) + double unixTi = GetUnixTi(command); + if (unixTi - epoch_unix_time > 0) { - converted_unix_time = (ti - epoch_unix_time)*10; + converted_unix_time = (uint) Math.Round((unixTi - epoch_unix_time)*10); } byte val = (byte)(converted_unix_time >> 24); packet[pos] = val; @@ -413,6 +418,7 @@ private void SetUdTi(byte[] packet, uint ti, UdExeType type) } else { + uint ti = GetTi(command); byte val = (byte)(ti >> 24); packet[pos] = val; val = (byte)(ti >> 16 & 0xff); diff --git a/aspnetapp/WINGS/Services/TMTC/Processor/UserDefined/SECONDARY_OBC/SecondaryObcTcPacketGenerator.cs b/aspnetapp/WINGS/Services/TMTC/Processor/UserDefined/SECONDARY_OBC/SecondaryObcTcPacketGenerator.cs index d3a6ef7..465e360 100644 --- a/aspnetapp/WINGS/Services/TMTC/Processor/UserDefined/SECONDARY_OBC/SecondaryObcTcPacketGenerator.cs +++ b/aspnetapp/WINGS/Services/TMTC/Processor/UserDefined/SECONDARY_OBC/SecondaryObcTcPacketGenerator.cs @@ -47,7 +47,6 @@ protected override byte[] GeneratePacket(Command command) var channelId = GetChannelId(command); var exeType = GetExeType(command); - var ti = GetTi(command); // ISSL Format Header // STX @@ -70,7 +69,7 @@ protected override byte[] GeneratePacket(Command command) SetUdCmdType(packet, UdCmdType.Sm); SetUdChannelId(packet, channelId); SetUdExeType(packet, exeType); - SetUdTi(packet, ti, exeType); + SetUdTi(packet, exeType, command); SetParams(packet, command.Params, UserDataPos + UserDataHdrLen); // CRC @@ -120,7 +119,11 @@ private UdExeType GetExeType(Command command) } private uint GetTi(Command command) { - return command.ExecTime; + return command.ExecTimeInt; + } + private double GetUnixTi(Command command) + { + return command.ExecTimeDouble; } private void SetTcpVerNum(byte[] packet, TcpVer ver) @@ -207,16 +210,17 @@ private void SetUdExeType(byte[] packet, UdExeType type) int pos = UserDataPos + 3; packet[pos] = (byte)type; } - private void SetUdTi(byte[] packet, uint ti, UdExeType type) + private void SetUdTi(byte[] packet, UdExeType type, Command command) { int pos = UserDataPos + 4; if(type == UdExeType.UnixTimeline) { - uint epoch_unix_time = 1577836800; // UNIX TIME of 2020/1/1 00:00:00(UTC) + double epoch_unix_time = 1577836800; // UNIX TIME of 2020/1/1 00:00:00(UTC) uint converted_unix_time = 0; - if (ti - epoch_unix_time > 0) + double unixTi = GetUnixTi(command); + if (unixTi - epoch_unix_time > 0) { - converted_unix_time = (ti - epoch_unix_time)*10; + converted_unix_time = (uint) Math.Round((unixTi - epoch_unix_time)*10); } byte val = (byte)(converted_unix_time >> 24); packet[pos] = val; @@ -229,6 +233,7 @@ private void SetUdTi(byte[] packet, uint ti, UdExeType type) } else { + uint ti = GetTi(command); byte val = (byte)(ti >> 24); packet[pos] = val; val = (byte)(ti >> 16 & 0xff); diff --git a/mysql/init/init.sql b/mysql/init/init.sql index ae39a4f..99613b0 100644 --- a/mysql/init/init.sql +++ b/mysql/init/init.sql @@ -35,7 +35,8 @@ CREATE TABLE IF NOT EXISTS `CommandLogs` ( `SentAt` datetime(1) NOT NULL, `OperationId` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `ExecType` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, - `ExecTime` int unsigned NOT NULL, + `ExecTimeInt` int unsigned NOT NULL, + `ExecTimeDouble` double DEFAULT NULL, `CmdName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, `Param1` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, `Param2` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,