Skip to content

Commit

Permalink
Merge branch 'develop-cfs-handlers' into develop. Close #234.
Browse files Browse the repository at this point in the history
**Description**

The cFS backend currently generates code that would normally have to be
adjusted by the user. The default cFS template assumes that there's only one
error handler, and it's name is fixed to `split`. This is clearly sub-ideal: we
want users to be able to generate code that they do not have to modify.

The `cfs` command should be modified to accept a handlers file, and the cFS
backend and template should be adjusted accordingly.

**Type**

- Feature: Improve capabilities of cFS backend.

**Additional context**

None.

**Requester**

- Ivan Perez.

**Method to check presence of bug**

Not applicable (not a bug).

**Expected result**

The `cfs` command accepts a handlers file as argument, and it is used in the
cFS backend to customize the shape of the cFS application.

The following Dockerfile checks that generating a cFS application with and
without the feature proposed renders the same result, after which it prints the
message "Success". There's a slight difference in the text published in the
events (they now contain the name of the handler or trigger activated), so that
different is disregarded. It requires an additional BASE_COMMIT variable
pointing to a commit prior to merging this feature.

```
FROM ubuntu:focal

ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update

RUN apt-get install --yes \
      curl g++ gcc git libgmp3-dev libz-dev make pkg-config

RUN mkdir -p $HOME/.local/bin
ENV PATH=$PATH:/root/.local/bin/

RUN curl https://downloads.haskell.org/~ghcup/0.1.17.7/x86_64-linux-ghcup-0.1.17.7 -o $HOME/.local/bin/ghcup
RUN chmod a+x $HOME/.local/bin/ghcup

ENV PATH=$PATH:/root/.ghcup/bin/
RUN ghcup install ghc 9.10
RUN ghcup install cabal 3.12
RUN ghcup set ghc 9.10.1
RUN cabal update

SHELL ["/bin/bash", "-c"]
CMD git clone $REPO \
    && cd $NAME \
    && git checkout $BASE_COMMIT \
    && cabal install ogma-cli:ogma \
    && ogma cfs --variable-file ogma-cli/examples/cfs-variables --variable-db ogma-cli/examples/cfs-variable-db --app-target-dir original \
    && git checkout $COMMIT \
    && cabal install --overwrite-policy=always ogma-cli:ogma \
    && ogma cfs --variable-file ogma-cli/examples/cfs-variables --variable-db ogma-cli/examples/cfs-variable-db --app-target-dir updated --handlers-file ogma-cli/examples/cfs-handlers \
    && sed -i -e 's/violation: split/violation/g' updated/fsw/src/copilot_cfs.c \
    && diff -rq original updated \
    && echo "Success"
```

Command (substitute variables based on new path after merge):
```sh
$ docker run -e "REPO=https://github.com/NASA/ogma" -e "NAME=ogma" -e "BASE_COMMIT=943bcbd83d1bd2075482c7f2beeca62751559b50" -e "COMMIT=<HASH>" -it ogma-verify-234
```

**Proposed solution**

Modify `ogma-cli`'s `cfs` CLI command to accept a handlers file, and pass it on
to the backend in `ogma-core`.

Modify `ogma-core`'s cFS backend to accept a handlers file, read all the
handlers listed inside, and pass their names to the template.

Modify `ogma-core`'s cFS template to generate a handler for each of the
handlers listed in the handlers file.

Add a new example handlers file to the `ogma-cli/examples` directory.

Update README to document new argument, new variable available to template, and
remove limitations that no longer apply.

**Further notes**

None.
  • Loading branch information
ivanperez-keera committed Feb 3, 2025
2 parents 943bcbd + dcc5f1e commit f055418
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 26 deletions.
3 changes: 2 additions & 1 deletion ogma-cli/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
# Revision history for ogma-cli

## [1.X.Y] - 2025-02-02
## [1.X.Y] - 2025-02-03

* Add all auxiliary test files to distributable Cabal package (#216).
* Remove extraneous EOL character (#224).
* Update installation instructions to use cabal install (#149).
* Update README with new cFS template variables (#229).
* Expose handlers-file argument to cFS backend (#234).

## [1.6.0] - 2025-01-21

Expand Down
20 changes: 10 additions & 10 deletions ogma-cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,11 +133,13 @@ four main arguments:
be made available to the monitor.
- `--variable-db FILENAME`: a file containing a database of known variables,
and the message they are included with.
- `--handlers-file FILENAME`: a file containing a list of known fault handlers
or triggers.

The following execution generates an initial cFS application for runtime
monitoring using Copilot:
```
$ ogma cfs --variable-db examples/cfs-variable-db --variable-file examples/cfs-variables
$ ogma cfs --variable-db examples/cfs-variable-db --variable-file examples/cfs-variables --handlers-file examples/cfs-handlers
```

The application generated by Ogma contains the following files:
Expand All @@ -155,15 +157,9 @@ copilot-cfs-demo/fsw/src/copilot_cfs.h
```

Users are expected to modify `Properties.hs` to adjust the property being
monitored. Although it is possible to adjust the file `copilot_cfs.c` to
include property violation handlers, we recommend adding them in a separate C
file and modifying the compilation scripts to include that additional file.
That way, invoking Ogma again will not overwrite the changes made to the cFS
application.

In this particular example, the C code generated contains the following
instruction to subscribe to an `ICAROUS_POSITION_MID` message to obtain
the vehicle position:
monitored. In this particular example, the C code generated contains the
following instruction to subscribe to an `ICAROUS_POSITION_MID` message to
obtain the vehicle position:
```c
CFE_SB_Subscribe(ICAROUS_POSITION_MID, COPILOT_CommandPipe);
```
Expand Down Expand Up @@ -235,6 +231,10 @@ the processing to an auxiliary function.
they carry, and their names. For each item, a `{{msgDataDesc}}`,
`{{msgDataVarName}}` and a `{{msgDataVarType}}` are defined.
- `{{triggers}}`: list of error handlers or fault triggers, which will be used
by the monitoring application to notify of faults or updates from the
monitoring system.
We understand that this level of customization may be insufficient for your
application. If that is the case, feel free to reach out to our team to discuss
how we could make the template expansion system more versatile.
Expand Down
1 change: 1 addition & 0 deletions ogma-cli/examples/cfs-handlers
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
split
14 changes: 14 additions & 0 deletions ogma-cli/src/CLI/CommandCFSApp.hs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ data CommandOpts = CommandOpts
, cFSAppTemplateDir :: Maybe String
, cFSAppVarNames :: String
, cFSAppVarDB :: Maybe String
, cFSAppHandlers :: Maybe String
}

-- | Create <https://cfs.gsfc.nasa.gov/ NASA core Flight System> (cFS)
Expand All @@ -74,6 +75,7 @@ command c =
(cFSAppTemplateDir c)
(cFSAppVarNames c)
(cFSAppVarDB c)
(cFSAppHandlers c)

-- * CLI

Expand Down Expand Up @@ -113,6 +115,13 @@ commandOptsParser = CommandOpts
<> help strCFSAppVarDBArgDesc
)
)
<*> optional
( strOption
( long "handlers-file"
<> metavar "FILENAME"
<> help strCFSAppHandlerListArgDesc
)
)

-- | Argument target directory to cFS app generation command
strCFSAppDirArgDesc :: String
Expand All @@ -132,3 +141,8 @@ strCFSAppVarListArgDesc =
strCFSAppVarDBArgDesc :: String
strCFSAppVarDBArgDesc =
"File containing a DB of known cFS/ICAROUS variables"

-- | Argument handler list to cFS app generation command
strCFSAppHandlerListArgDesc :: String
strCFSAppHandlerListArgDesc =
"File containing list of Copilot handlers used in the specification"
1 change: 1 addition & 0 deletions ogma-core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
* Make structured data available to cFS template (#229).
* Update Copilot struct code generator to use new function names (#231).
* Simplify Copilot struct definitions by using generics (#199).
* Update cFS backend to process a handlers file (#234).

## [1.6.0] - 2025-01-21

Expand Down
72 changes: 59 additions & 13 deletions ogma-core/src/Command/CFSApp.hs
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,15 @@ module Command.CFSApp
where

-- External imports
import qualified Control.Exception as E
import Data.Aeson (ToJSON (..), decode)
import Data.List (find)
import Data.Text (Text)
import Data.Text.Lazy (unpack)
import GHC.Generics (Generic)
import System.FilePath ( (</>) )
import qualified Control.Exception as E
import Control.Monad.Except ( ExceptT (..), liftEither, runExceptT,
throwError )
import Data.Aeson ( ToJSON (..), decode )
import Data.List ( find )
import Data.Text ( Text )
import Data.Text.Lazy ( unpack )
import GHC.Generics ( Generic )
import System.FilePath ( (</>) )

-- Internal imports: auxiliary
import Command.Result ( Result (..) )
Expand All @@ -71,8 +73,11 @@ cFSApp :: FilePath -- ^ Target directory where the application
-> Maybe FilePath -- ^ File containing a list of known variables
-- with their types and the message IDs they
-- can be obtained from.
-> Maybe FilePath -- ^ File containing a list of handlers used in the
-- Copilot specification. The handlers are assumed
-- to receive no arguments.
-> IO (Result ErrorCode)
cFSApp targetDir mTemplateDir varNameFile varDBFile = do
cFSApp targetDir mTemplateDir varNameFile varDBFile handlersFile = do

-- We first try to open the two files we need to fill in details in the CFS
-- app template.
Expand All @@ -85,9 +90,12 @@ cFSApp targetDir mTemplateDir varNameFile varDBFile = do
Nothing -> return knownVars
Just fn -> fmap read <$> lines <$> readFile fn

case varDBE of
Left e -> return $ cannotOpenDB varDBFile e
Right varDB -> do
handlersE <- parseOptionalRequirementsListFile handlersFile

case (varDBE, handlersE) of
(Left e, _) -> return $ cannotOpenDB varDBFile e
(_, Left e) -> return $ cannotOpenHandlers handlersFile e
(Right varDB, Right handlers) -> do

-- The variable list is mandatory. This check fails if the filename
-- provided does not exist or if the file cannot be opened. The condition
Expand Down Expand Up @@ -118,7 +126,7 @@ cFSApp targetDir mTemplateDir varNameFile varDBFile = do
-- This is a Data.List.unzip4
let (vars, ids, infos, datas) = foldr f ([], [], [], []) varNames

let subst = toJSON $ appComponents vars ids infos datas
let subst = toJSON $ appComponents vars ids infos datas handlers

-- Expand template
copyTemplate templateDir subst targetDir
Expand Down Expand Up @@ -185,21 +193,37 @@ data MsgData = MsgData

instance ToJSON MsgData

-- | The message ID to subscribe to.
type Trigger = String

-- | Data that may be relevant to generate a cFS monitoring application.
data AppData = AppData
{ variables :: [VarDecl]
, msgIds :: [MsgInfoId]
, msgCases :: [MsgInfo]
, msgHandlers :: [MsgData]
, triggers :: [Trigger]
}
deriving (Generic)

instance ToJSON AppData

-- | Return the components that are customized in a cFS application.
appComponents :: [VarDecl] -> [MsgInfoId] -> [MsgInfo] -> [MsgData] -> AppData
appComponents :: [VarDecl]
-> [MsgInfoId]
-> [MsgInfo]
-> [MsgData]
-> [Trigger]
-> AppData
appComponents = AppData

-- | Process a requirements / handlers list file, if available, and return the
-- handler names.
parseOptionalRequirementsListFile :: Maybe FilePath
-> IO (Either E.SomeException [String])
parseOptionalRequirementsListFile Nothing = return $ Right []
parseOptionalRequirementsListFile (Just fp) = E.try $ lines <$> readFile fp

-- * Exception handlers

-- | Exception handler to deal with the case in which the variable DB cannot be
Expand Down Expand Up @@ -245,6 +269,20 @@ cannotCopyTemplate _e =
++ " there's free space in the disk and that you have the necessary"
++ " permissions to write in the destination directory."

-- | Exception handler to deal with the case in which the handlers file cannot
-- be opened.
cannotOpenHandlers :: Maybe FilePath -> E.SomeException -> Result ErrorCode
cannotOpenHandlers Nothing _e =
Error ecCannotOpenHandlersCritical msg LocationNothing
where
msg =
"cannotOpenDB: this is a bug. Please notify the developers"
cannotOpenHandlers (Just file) _e =
Error ecCannotOpenHandlersUser msg (LocationFile file)
where
msg =
"cannot open handlers file " ++ file

-- * Error codes

-- | Encoding of reasons why the command can fail.
Expand All @@ -260,6 +298,14 @@ ecCannotOpenDBCritical = 2
ecCannotOpenDBUser :: ErrorCode
ecCannotOpenDBUser = 1

-- | Internal error: handlers file cannot be opened.
ecCannotOpenHandlersCritical :: ErrorCode
ecCannotOpenHandlersCritical = 2

-- | Error: the handlers file provided by the user cannot be opened.
ecCannotOpenHandlersUser :: ErrorCode
ecCannotOpenHandlersUser = 1

-- | Error: the variable file provided by the user cannot be opened.
ecCannotOpenVarFile :: ErrorCode
ecCannotOpenVarFile = 1
Expand Down
6 changes: 4 additions & 2 deletions ogma-core/templates/copilot-cfs/fsw/src/copilot_cfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,10 +166,12 @@ void COPILOT_Process{{msgDataDesc}}(void)
{{/msgHandlers}}


{{#triggers}}
/**
* Report copilot property violations.
*/
void split(void) {
void {{.}}(void) {
CFE_EVS_SendEvent(COPILOT_COMMANDCPVIOL_INF_EID, CFE_EVS_ERROR,
"COPILOT: violation");
"COPILOT: violation: {{.}}");
}
{{/triggers}}

0 comments on commit f055418

Please sign in to comment.