diff --git a/.github/git-pr-release-template.erb b/.github/git-pr-release-template.erb new file mode 100644 index 0000000..a47b522 --- /dev/null +++ b/.github/git-pr-release-template.erb @@ -0,0 +1,3 @@ +<%= ENV['GIT_PR_RELEASE_TITLE'] %> + +<%= ENV['GIT_PR_RELEASE_BODY'] %> diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml new file mode 100644 index 0000000..d530f4d --- /dev/null +++ b/.github/release-drafter.yml @@ -0,0 +1,69 @@ +prerelease: true + +# Filter previous releases considering target_commitish +include-pre-releases: true +filter-by-commitish: true + +# Versioning configuration +tag: "v0.0.0" + +categories: + - title: 'BREAKING CHANGES' + labels: + - 'breaking' + - title: '💎 Features' + labels: + - 'feature' + - title: '🚀 Improvement' + labels: + - 'enhancement' + - title: '🐛 Bug Fixes' + labels: + - 'bug' + - title: '🧰 Maintenance' + labels: + - 'support' + - 'dependencies' + - title: '🧹 Chore' + labels: + - 'chore' + +category-template: '### $TITLE' + +change-title-escapes: '\<*_&#@`' # Updated to disable mentions and code blocks + +autolabeler: + - label: 'feature' + branch: + - '/^feat\/.+/' + - label: 'enhancement' + branch: + - '/^refac\/.+/' + - label: 'bug' + branch: + - '/^fix\/.+/' + title: + - '/^fix/i' + - label: 'support' + branch: + - '/^support\/.+/' + title: + - '/^support/i' + - '/^chore/i' + - '/^ci/i' + - '/^docs/i' + - '/^test/i' + +include-labels: + - breaking + - feature + - enhancement + - bug + - support + - dependencies + +exclude-labels: + - 'exclude-from-changelog' + +template: | + $CHANGES diff --git a/.github/workflows/draft-release.yml b/.github/workflows/draft-release.yml new file mode 100644 index 0000000..9f7b6ea --- /dev/null +++ b/.github/workflows/draft-release.yml @@ -0,0 +1,50 @@ +name: Draft Release + +on: + push: + branches: + - main + - dev/*.*.* + +permissions: + contents: write + actions: write # Necessary to cancel workflow executions + checks: write # Necessary to write reports + pull-requests: write # Necessary to comment on PRs + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + + # Refs: https://github.com/release-drafter/release-drafter + update-release-draft: + runs-on: ubuntu-latest + + outputs: + CURRENT_VERSION: ${{ steps.version.outputs.project_version }} + RELEASE_DRAFT_BODY: ${{ steps.release-drafter.outputs.body }} + + steps: + - uses: actions/checkout@v4 + with: + repository: ut-issl/c2a-generator + ssh-key: ${{ secrets.PRIVATE_REPO_SSH_KEY }} + + - name: Read version from pyproject.toml + id: version + run: | + version=$(awk -F\" '/version =/ {print $2}' pyproject.toml) + echo "::set-output name=project_version::$version" + + - uses: release-drafter/release-drafter@v6 + id: release-drafter + with: + config-name: release-drafter.yml + name: v${{ steps.version.outputs.project_version }} + tag: v${{ steps.version.outputs.project_version }} + version: ${{ steps.version.outputs.project_version }} + disable-autolabeler: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..753318e --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,56 @@ +name: Release + +on: + pull_request: + branches: + - release/current + - release/*.*.* + types: [closed] + +permissions: + contents: write + +jobs: + create-github-release: + + runs-on: ubuntu-latest + + if: github.event.pull_request.merged == true + + outputs: + RELEASED_VERSION: ${{ steps.version.outputs.project_version }} + + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.base.ref }} + + - name: Read version from pyproject.toml + id: version + run: | + version=$(awk -F\" '/version =/ {print $2}' pyproject.toml) + echo "::set-output name=project_version::$version" + + - name: Update Changelog + uses: stefanzweifel/changelog-updater-action@v1 + with: + latest-version: v${{ steps.version.outputs.project_version }} + release-notes: ${{ github.event.pull_request.body }} + + - name: Commit, Tag and Push + uses: stefanzweifel/git-auto-commit-action@v5 + with: + branch: ${{ github.event.pull_request.base.ref }} + commit_message: Release v${{ steps.version.outputs.project_version }} + tagging_message: v${{ steps.version.outputs.project_version }} + + - uses: softprops/action-gh-release@v2 + with: + body: ${{ github.event.pull_request.body }} + tag_name: v${{ steps.version.outputs.project_version }} + target_commitish: ${{ github.head_ref }} + + - name: Delete drafts + uses: hugo19941994/delete-draft-releases@v1.0.1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.python-version b/.python-version index 2c07333..e4fba21 100644 --- a/.python-version +++ b/.python-version @@ -1 +1 @@ -3.11 +3.12 diff --git a/c2a_generator/__init__.py b/c2a_generator/__init__.py index 1776e96..81fa5fc 100644 --- a/c2a_generator/__init__.py +++ b/c2a_generator/__init__.py @@ -4,6 +4,8 @@ from .cmd_csv import generate # noqa from .cmd_def_c import generate # noqa from .cmd_def_h import generate # noqa +from .eh_rules_c import generate # noqa +from .eh_rules_h import generate # noqa from .subobc_cmd_def_h import generate # noqa from .subobc_tlm_buf_c import generate # noqa from .subobc_tlm_buf_h import generate # noqa diff --git a/c2a_generator/eh_rules_c.py b/c2a_generator/eh_rules_c.py new file mode 100644 index 0000000..20c35d2 --- /dev/null +++ b/c2a_generator/eh_rules_c.py @@ -0,0 +1,54 @@ +import csv +from pathlib import Path + + +def generate(src_path: str, dest_path: Path, eh_header: str) -> None: + assert dest_path.parent.exists(), f"{dest_path} does not exist" + with open(src_path, "r", encoding="utf-8") as csv_file, open(dest_path, "w", encoding="utf-8") as src_file: + src_file.write( + f""" +#pragma section REPRO +/** + * @file + * @brief EH の Rule 共通コード + */ +{eh_header} + +void EH_load_default_rules(void) +{{ + EH_RuleSettings settings; + +"""[ + 1: + ] + ) + reader = csv.reader(csv_file) + headers = next(reader) + dict_reader = csv.DictReader(csv_file, fieldnames=headers) + for row in dict_reader: + if not any(row): + continue + code = "" + if row["description"]: + row_description = row["description"].replace("\n", "\n// ") + code += f" // {row_description}\n" + code += f" settings.event.group = {row['group']};\n" + code += f" settings.event.local = {row['local']};\n" + code += f" settings.event.err_level = EL_ERROR_LEVEL_{row['err_level']};\n" + code += f" settings.should_match_err_level = {1 if row['should_match_err_level'] == 'TRUE' else 0};\n" + code += f" settings.condition.type = EH_RESPONSE_CONDITION_{row['type'].upper()};\n" + code += f" settings.condition.count_threshold = {row['count_threshold']};\n" + code += f" settings.condition.time_threshold_ms = {int(float(row['time_threshold[s]']) * 1000)};\n" + code += f" settings.deploy_bct_id = {row['bc']};\n" + code += f" settings.is_active = {1 if row['should_match_err_level'] == 'TRUE' else 0};\n" + code += f" EH_register_rule({row['name']}, &settings);\n\n" + src_file.write(code) + src_file.write( + """} +} + +#pragma section +"""[ + 1: + ] + ) diff --git a/c2a_generator/eh_rules_h.py b/c2a_generator/eh_rules_h.py new file mode 100644 index 0000000..f6470ca --- /dev/null +++ b/c2a_generator/eh_rules_h.py @@ -0,0 +1,56 @@ +import csv +from pathlib import Path + + +def generate(src_path: str, dest_path: Path, base_id: int) -> None: + assert dest_path.parent.exists(), f"{dest_path} does not exist" + with open(src_path, "r", encoding="utf-8") as csv_file, open(dest_path, "w", encoding="utf-8") as header_file: + header_file.write( + """ +/** + * @file + * @brief EH の Rule 共通ヘッダ + */ +#ifndef EVENT_HANDLER_RULES_H_ +#define EVENT_HANDLER_RULES_H_ + +/** + * @enum EH_RULE_ID + * @brief EH_Rule の ID + * @note 最大数は EH_RULE_MAX で規定 + * @note uint16_t を想定 + */ +typedef enum +{ +"""[ + 1: + ] + ) + reader = csv.reader(csv_file) + headers = next(reader) + dict_reader = csv.DictReader(csv_file, fieldnames=headers) + for row in dict_reader: + if not any(row): + continue + try: + header_file.write(f' {row["name"]} = {base_id},\n') + base_id += 1 + except ValueError: + continue + header_file.write( + """ +} EH_RULE_ID; + + +/** + * @brief event_handler のデフォルトルールを読み込む + * @param void + * @return void + */ +void EH_load_default_rules(void); + +#endif +"""[ + 1: + ] + ) diff --git a/c2a_generator/wings_json.py b/c2a_generator/wings_json.py index 833894a..ad1abf0 100644 --- a/c2a_generator/wings_json.py +++ b/c2a_generator/wings_json.py @@ -26,6 +26,9 @@ def generate( aobc_csv_path: Optional[Path] = None, tobc_csv_path: Optional[Path] = None, mif_csv_path: Optional[Path] = None, + eh_src: Optional[Path] = None, + eh_base_id: int = 0, + eh_list: list = [], ) -> None: data = [] if aobc_csv_path: @@ -37,7 +40,20 @@ def generate( if mif_csv_path: mif_bc_dict = csv_to_json(mif_csv_path) data.append({"obc_name": "MIF", "bc": mif_bc_dict, "el": [], "eh": []}) - data.append({"obc_name": "MOBC", "bc": [], "el": [], "eh": []}) + if eh_src: + with open(eh_src, "r", encoding="utf-8") as src_file: + reader = csv.reader(src_file) + headers = next(reader) + dict_reader = csv.DictReader(src_file, fieldnames=headers) + + for row in dict_reader: + if not any(row): + continue + if not row["name"].strip(): + continue + eh_list.append({"name": row["name"], "id": eh_base_id}) + eh_base_id += 1 + data.append({"obc_name": "MOBC", "bc": [], "el": [], "eh": eh_list}) bcid = 0 for src_path, bcid_base in bct_src: if bcid_base is not None: diff --git a/c2a_generator_config.toml b/c2a_generator_config.toml deleted file mode 100644 index c6e808b..0000000 --- a/c2a_generator_config.toml +++ /dev/null @@ -1,25 +0,0 @@ -c2a_user_root="tmp" - -[[obc]] -is_main_obc=true -tlm_prefix="ISSL6U_MOBC_TLM_DB_" -tlm_src="../tlm/ong_mobc/" -cmd_src="../cmd/ong_mobc.csv" -bct_src="../bct/ong_mobc.csv" -tlm_id_range=["0x00", "0x100"] -tlm_wings_dest="./../wings_data/tlm/" -cmd_wings_dest="./../wings_data/cmd/ISSL6U_MOBC_CMD_DB_CMD_DB.csv" -bct_wings_dest="./../wings_data/bct/ISSL6U_MOBC_CMD_DB_BCT.csv" - -[[obc]] -is_main_obc=false -is_enable=true -name="AOBC" -tlm_src="../tlm/ong_aobc/" -cmd_src="../cmd/ong_mobc.csv" -max_tlm_num=256 -driver_path="Aocs" -driver_type="AOBC_Driver" -driver_name="aobc_driver" -code_when_tlm_not_found="aobc_driver->info.comm.rx_err_code = AOBC_RX_ERR_CODE_TLM_NOT_FOUND;" -tlm_id_range=["0x00", "0xff"] diff --git a/test.py b/example.py similarity index 68% rename from test.py rename to example.py index 4c2fe66..d573a8b 100644 --- a/test.py +++ b/example.py @@ -6,6 +6,36 @@ Path(__file__).parent.parent / "sils-docker/sils/FlightSW/c2a-mobc-onglaisat" ) +# eh +c2a_generator.eh_rules_h.generate( + root_path / "design/eh.csv", + root_path / "src/src_user/Settings/System/EventHandlerRules/event_handler_rules.h", + base_id=9 +) +c2a_generator.eh_rules_c.generate( + root_path / "design/eh.csv", + root_path / "src/src_user/Settings/System/EventHandlerRules/event_handler_rules.c", + eh_header=""" +#include "event_handler_rules.h" +#include +#include "../../../TlmCmd/block_command_definitions.h" +#include "../../../TlmCmd/block_command_definitions.h" +#include "../../../IfWrapper/uart_user.h" + +#include "../../../Applications/UserDefined/Cdh/uart_fault_recovery.h" +#include "../../../Applications/UserDefined/Cdh/mode_monitor.h" +#include "../../../Applications/UserDefined/Power/under_voltage_control_utility.h" +#include "../../../Applications/UserDefined/Power/under_voltage_control.h" +#include "../../../Applications/UserDefined/Power/over_current.h" +#include "../../../Applications/UserDefined/Thermal/mobc_temperature_monitor.h" +#include "../../../Applications/UserDefined/Thermal/high_temperature_deviation_control.h" +#include "../../../Applications/UserDefined/Thermal/bat_heater_control.h" +#include "../../../Applications/UserDefined/Mission/mission_sequence.h" +#include "../../../Applications/UserDefined/Mission/rsi_sun_angle.h" +#include "../../../Applications/UserDefined/Com/comm_fdir.h" +""" +) + # cmd c2a_generator.cmd_def_c.generate( root_path / "design/cmd.csv", @@ -101,4 +131,15 @@ bct_src, root_path / "../../../wings/aspnetapp/WINGS/ClientApp/src/assets/alias/c2a_onglai.json", + eh_src=root_path / "design/eh.csv", + eh_base_id=9, + eh_list=[], +) + +c2a_generator.wings_json.generate( + bct_src, + root_path / "database/c2a_onglai.json", + eh_src=root_path / "design/eh.csv", + eh_base_id=9, + eh_list=[], ) diff --git a/legacy_csv_converter_config.toml b/legacy_csv_converter_config.toml deleted file mode 100644 index 64315e7..0000000 --- a/legacy_csv_converter_config.toml +++ /dev/null @@ -1,4 +0,0 @@ -[tlm] -src_path="../../sils-docker/sils/FlightSW/c2a-tobc/database/TLM_DB" -dest_path="../tlm/ong_tobc" -src_prefix="ISSL6U_TOBC_TLM_DB_" diff --git a/main.py b/main.py deleted file mode 100644 index f643a13..0000000 --- a/main.py +++ /dev/null @@ -1,73 +0,0 @@ -import argparse -from pathlib import Path - -import c2a_generator -import toml - - -def main(root_path: str, toml_path: str, export_wings: bool = False) -> None: - config = toml.load(toml_path) - assert config.get("obc") is not None, "obc is not defined in config.toml" - assert config.get("c2a_user_root") is not None, "c2a_root is not defined in config.toml" - c2a_user_path = root_path / config["c2a_user_root"] - - for obc in config["obc"]: - if obc.get("is_main_obc"): - c2a_generator.bct_def_h.generate(root_path / obc["bct_src"], c2a_user_path / "TlmCmd/block_command_definitions.h") - c2a_generator.cmd_def_h.generate(root_path / obc["cmd_src"], c2a_user_path / "TlmCmd/command_definitions.h") - c2a_generator.cmd_def_c.generate(root_path / obc["cmd_src"], c2a_user_path / "TlmCmd/command_definitions.c") - c2a_generator.tlm_def_h.generate(root_path / obc["tlm_src"], c2a_user_path / "TlmCmd/telemetry_definitions.h") - c2a_generator.tlm_def_c.generate(root_path / obc["tlm_src"], c2a_user_path / "TlmCmd/telemetry_definitions.c") - if export_wings: - c2a_generator.cmd_csv.generate(root_path / obc["cmd_src"], root_path / obc["cmd_wings_dest"]) - c2a_generator.bct_csv.generate(root_path / obc["bct_src"], root_path / obc["bct_wings_dest"]) - c2a_generator.tlm_csv.generate(root_path / obc["tlm_src"], root_path / obc["tlm_wings_dest"], obc["tlm_prefix"]) - elif obc.get("is_enable"): - key_list = ["driver_path", "name", "driver_type", "driver_name", "max_tlm_num", "code_when_tlm_not_found"] - for key in key_list: - assert obc.get(key) is not None, f"{key} is not defined in config.toml" - c2a_generator.subobc_cmd_def_h.generate( - root_path / obc["cmd_src"], - c2a_user_path / "Driver" / obc["driver_path"] / f"{obc['name'].lower()}_command_definitions.h", - obc_name=obc["name"].upper(), - ) - c2a_generator.subobc_tlm_def_h.generate( - root_path / obc["tlm_src"], - c2a_user_path / "Driver" / obc["driver_path"] / f"{obc['name'].lower()}_telemetry_definitions.h", - obc_name=obc["name"].upper(), - ) - c2a_generator.subobc_tlm_buf_c.generate( - root_path / obc["tlm_src"], - c2a_user_path / "Driver" / obc["driver_path"] / f"{obc['name'].lower()}_telemetry_buffer.c", - obc_name=obc["name"].upper(), - driver_type=obc["driver_type"], - driver_name=obc["driver_name"], - code_when_tlm_not_found=obc["code_when_tlm_not_found"], - ) - c2a_generator.subobc_tlm_buf_h.generate( - root_path / obc["tlm_src"], - c2a_user_path / "Driver" / obc["driver_path"] / f"{obc['name'].lower()}_telemetry_buffer.h", - obc_name=obc["name"].upper(), - driver_type=obc["driver_type"], - driver_name=obc["driver_name"], - max_tlm_num=obc["max_tlm_num"], - ) - c2a_generator.subobc_tlm_data_def_h.generate( - root_path / obc["tlm_src"], - c2a_user_path / "Driver" / obc["driver_path"] / f"{obc['name'].lower()}_telemetry_data_definitions.h", - obc["name"].upper(), - ) - - -if __name__ == "__main__": - parser = argparse.ArgumentParser() - parser.add_argument("--wings", action="store_true", default=False, help="Perform special processing when --wings is specified") - parser.add_argument("--config", type=str, required=True, help="Path to the config TOML file") - args = parser.parse_args() - - toml_path = Path(args.config) - if not toml_path.exists(): - print(f"Error: The specified config file does not exist at {toml_path}") - else: - root_path = toml_path.parent - main(root_path, toml_path, args.wings) diff --git a/pyproject.toml b/pyproject.toml index 0625afa..78c1053 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "c2a_generator" -version = "0.1.2" +version = "0.1.0" description = "Add your description here" authors = [ { name = "flap1", email = "sho1seto@gmail.com" }