{"id":18103938,"url":"https://github.com/svoop/notam","last_synced_at":"2025-04-13T19:30:30.807Z","repository":{"id":57901776,"uuid":"473686129","full_name":"svoop/notam","owner":"svoop","description":"Parser for NOTAM (Notice to Air Missions)","archived":false,"fork":false,"pushed_at":"2024-12-27T12:51:39.000Z","size":223,"stargazers_count":14,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-27T10:11:09.556Z","etag":null,"topics":["aviation","gem","openflightmaps","ruby"],"latest_commit_sha":null,"homepage":"https://bitcetera.com","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/svoop.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null},"funding":{"github":"svoop","custom":"https://donorbox.org/bitcetera"}},"created_at":"2022-03-24T16:26:33.000Z","updated_at":"2024-12-27T12:51:34.000Z","dependencies_parsed_at":"2023-12-29T01:24:22.909Z","dependency_job_id":"25604622-3ed1-4b1c-be57-5a188e56edfd","html_url":"https://github.com/svoop/notam","commit_stats":{"total_commits":52,"total_committers":2,"mean_commits":26.0,"dds":"0.038461538461538436","last_synced_commit":"081b431329439879c7f5494cc559c8ef65cf133e"},"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/svoop%2Fnotam","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/svoop%2Fnotam/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/svoop%2Fnotam/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/svoop%2Fnotam/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/svoop","download_url":"https://codeload.github.com/svoop/notam/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248487689,"owners_count":21112191,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aviation","gem","openflightmaps","ruby"],"created_at":"2024-10-31T22:13:34.245Z","updated_at":"2025-04-13T19:30:30.783Z","avatar_url":"https://github.com/svoop.png","language":"Ruby","readme":"[![Version](https://img.shields.io/gem/v/notam.svg?style=flat)](https://rubygems.org/gems/notam)\n[![Tests](https://img.shields.io/github/actions/workflow/status/svoop/notam/test.yml?style=flat\u0026label=tests)](https://github.com/svoop/notam/actions?workflow=Test)\n[![Code Climate](https://img.shields.io/codeclimate/maintainability/svoop/notam.svg?style=flat)](https://codeclimate.com/github/svoop/notam/)\n[![GitHub Sponsors](https://img.shields.io/github/sponsors/svoop.svg)](https://github.com/sponsors/svoop)\n\n# NOTAM\n\nParser for [NOTAM (Notice to Air Missions)](https://www.icao.int/safety/istars/pages/notams.aspx) messages in Ruby.\n\n* [Homepage](https://github.com/svoop/notam)\n* [API](https://www.rubydoc.info/gems/notam)\n* Author: [Sven Schwyn - Bitcetera](https://bitcetera.com)\n\nThank you for supporting free and open-source software by sponsoring on [GitHub](https://github.com/sponsors/svoop) or on [Donorbox](https://donorbox.com/bitcetera). Any gesture is appreciated, from a single Euro for a ☕️ cup of coffee to 🍹 early retirement.\n\n## Install\n\n### Security\n\nThis gem is [cryptographically signed](https://guides.rubygems.org/security/#using-gems) in order to assure it hasn't been tampered with. Unless already done, please add the author's public key as a trusted certificate now:\n\n```\ngem cert --add \u003c(curl -Ls https://raw.github.com/svoop/notam/main/certs/svoop.pem)\n```\n\n### Bundler\n\nAdd the following to the `Gemfile` or `gems.rb` of your [Bundler](https://bundler.io) powered Ruby project:\n\n```ruby\ngem 'notam'\n```\n\nAnd then install the bundle:\n\n```\nbundle install --trust-policy MediumSecurity\n```\n\n## Usage\n\n```ruby\nraw_notam_text_message = \u003c\u003c~END\n  W0902/22 NOTAMN\n  Q) LSAS/QRRCA/V/BO/W/000/148/4624N00702E004\n  A) LSAS PART 2 OF 3 B) 2204110900 C) 2205131400 EST\n  D) APR 11 SR MINUS15-1900, 20-21 26-28 MAY 03-05 10-12 0530-2100, APR\n  14 22 29 MAY 06 13 0530-1400, APR 19 25 MAY 02 09 0800-2100\n  E) R-AREA LS-R7 HONGRIN ACT DUE TO FRNG.\n  F) GND\n  G) 14800FT AMSL\n  END PART 2 OF 3\n  CREATED: 11 Apr 2022 06:10:00\n  SOURCE: LSSNYNYX\nEND\n\nnotam = NOTAM.parse(raw_notam_text_message)\nnotam.data    # =\u003e Hash\n```\n\nThe resulting hash for this example looks as follows:\n\n```ruby\n{\n  id: \"W0902/22\",\n  id_series: \"W\",\n  id_number: 902,\n  id_year: 2022,\n  new?: true,\n  fir: \"LSAS\",\n  subject_group: :airspace_restrictions,\n  subject: :restricted_area,\n  condition_group: :changes,\n  condition: :activated,\n  traffic: :vfr,\n  purpose: [:operational_significance, :flight_operations],\n  scope: [:navigation_warning],\n  lower_limit: #\u003cAIXM::Z 14800 ft QNH\u003e,\n  upper_limit: #\u003cAIXM::Z 0 ft QFE\u003e,\n  center_point: #\u003cAIXM::XY 46.40000000N 007.03333333E\u003e,\n  radius: #\u003cAIXM::D 4.0 nm\u003e,\n  locations: [\"LSAS\"],\n  part_index: 2,\n  part_index_max: 3,\n  effective_at: 2022-04-11 09:00:00 UTC,\n  expiration_at: 2022-05-13 14:00:00 UTC,\n  estimated_expiration?: false,\n  no_expiration?: true,\n  schedules: [\n    #\u003cNOTAM::Schedule actives: [2022-04-11], times: [sunrise-15min..19:00 UTC], inactives: []\u003e,\n    #\u003cNOTAM::Schedule actives: [2022-04-20..2022-04-21, 2022-04-26..2022-04-28, 2022-05-03..2022-05-05, 2022-05-10..2022-05-12], times: [05:30 UTC..21:00 UTC], inactives: []\u003e,\n    #\u003cNOTAM::Schedule actives: [2022-04-14, 2022-04-22, 2022-04-29, 2022-05-06, 2022-05-13], times: [05:30 UTC..14:00 UTC], inactives: []\u003e,\n    #\u003cNOTAM::Schedule actives: [2022-04-19, 2022-04-25, 2022-05-02, 2022-05-09], times: [08:00 UTC..21:00 UTC], inactives: []\u003e\n  ],\n  five_day_schedules: [\n    #\u003cNOTAM::Schedule actives: [2022-04-11], times: [04:35 UTC..19:00 UTC], inactives: []\u003e,\n    #\u003cNOTAM::Schedule actives: [2022-04-14], times: [05:30 UTC..14:00 UTC], inactives: []\u003e\n  ],\n  content: \"R-AREA LS-R7 HONGRIN ACT DUE TO FRNG.\",\n  translated_content: \"R-AREA LS-R7 HONGRIN ACTIVE DUE TO FRNG.\",\n  created: 2022-04-11 06:10:00 UTC,\n  source: \"LSSNYNYX\"\n}\n```\n\nA few highlights to note here:\n\n* Value classes of the [AIXM gem](https://rubygems.org/gems/aixm) are used to ease further processing.\n* Schedules can be pretty complex, therefore a simpler `five_day_schedule` is calculated for the day the NOTAM becomes effective and the four subsequent days. This short term schedule does not contain exceptions nor events such as sunrises anymore. Furthermore, you can calculate different custom sub-schedules using `slice` and `resolve`.\n* Content is processed to `translated_content`. As of now, known english contractions are expanded. Feel free to contribute non-english locale files read by the [I18n gem](https://rubygems.org/gems/i18n).\n\nSince NOTAM may contain a certain level of redundancy, the parser does some integrity checks, fixes the payload if possible and issues a warning.\n\nYou get a `NOTAM::ParseError` in case the raw NOTAM text message fails to be parsed. This error object features two notable methods:\n\n* `item` – the faulty item (if already available)\n* `cause` – the underlying error object (if any)\n\nIf you're sure the NOTAM is correct, please [submit an issue](#development) or fix the bug and [submit a pull request](#development).\n\nSee the [API documentation](https://www.rubydoc.info/gems/notam) for more.\n\n⚠️ Only NOTAM compatible with the ICAO annex 15 are supported for now. Most notably in the USA other NOTAM formats exist which cannot be parsed using this gem.\n\n### Anatomy of a NOTAM message\n\nA NOTAM message consists of the following items in order:\n\n* Header: ID and type of NOTAM\n* [Q item](https://www.rubydoc.info/gems/notam/NOTAM/Q): Essential information such as purpose or center point and radius\n* [A item](https://www.rubydoc.info/gems/notam/NOTAM/A): Affected locations\n* [B item](https://www.rubydoc.info/gems/notam/NOTAM/B): When the NOTAM becomes effective\n* [C item](https://www.rubydoc.info/gems/notam/NOTAM/C): When the NOTAM expires\n* [D item](https://www.rubydoc.info/gems/notam/NOTAM/D): Activity schedules (optional)\n* [E item](https://www.rubydoc.info/gems/notam/NOTAM/E): Free text description\n* [F item](https://www.rubydoc.info/gems/notam/NOTAM/F): Upper limit (optional)\n* [G item](https://www.rubydoc.info/gems/notam/NOTAM/G): Lower limit (optional)\n* Footer: Any number of lines with metadata such as `CREATED` and `SOURCE`\n\nFurthermore, oversized NOTAM may be split into several partial messages which contain with `PART n OF n` and `END PART n OF n` markers. This is an unofficial extension and therefore the markers may be found in different places such as on the A item, on the E item or even somewhere in between.\n\n### FIR\n\nFour letter FIR codes assigned by the ICAO follow some logic, albeit there exist exceptions and inconsistencies e.g. for historical reasons. Let's take an easy example:\n\n```\nL F M M\n┬ ┬ ─┬─\n│ │  └─ subsection: MM =\u003e Marseille\n│ └──── geopolitical unit: F =\u003e France\n└────── global area: L =\u003e lower Europe\n```\n\nThe informal use of only the first two letters often stands for a combination of all subsections contained therein. Example: `LF` is a combination of `LFBB`, `LFEE`, `LFFF`, `LFMM` and `LFRR`.\n\nFIR codes ending with `XX` specify more than one subsection. Example: `LFXX` can be any combination of at least two subsections within `LF`. In NOTAM, this notation may be used on the Q item if (and only if) the affected subsections are listed on the A item.\n\n### Series\n\nThe first letter of the NOTAM ID is identifying the series. The following example is part of series `S`:\n\n```\nS0054/02 NOTAMN\n```\n\nAIS are free to define series as they please, however, a few conventions have emerged:\n\n* **Series A**\u003cbr\u003eGeneral rules, en-route navigation and communication facilities, airspace restrictions and activities taking place above FL 245 as well as information concerning major international aerodromes.\n* **Series B**\u003cbr\u003eInformation on airspace restrictions, on activities taking place at or below FL 245 and on other international aerodromes at which IFR flights are permitted.\n* **Series C**\u003cbr\u003eInformation on other international aerodromes at which only VFR flights are permitted.\n* **Series D**\u003cbr\u003eInformation on national aerodromes\n* **Series E**\u003cbr\u003eInformation on heliports\n* **Series S** (aka: SNOWTAM)\u003cbr\u003eSurface condition reports\n* **Series T**\u003cbr\u003eReserved for NOTAM processing units in cases when basic operational information was not triggered by the issuing AIS.\n* **Series V** (aka: ASHTAM)\u003cbr\u003eVolcano ash condition reports\n\n### Special NOTAM\n\n#### Checklist\n\nChecklist NOTAM are periodically issued lists of all currently effective NOTAM. They are used for cross checking and can usually be ignored for flight planning. Their Q item contain `QKKKK` which is decoded as `condition: :checklist`, here's an example:\n\n```\nQ) EDXX/QKKKK/K /K  /K /000/999/5123N01018E999\n        ^^^^^\n```\n\n#### Trigger\n\nTrigger NOTAM are referring to another source of information such as AIP SUP (AIP supplement). Their Q item contain `Q..TT` which is decoded as `condition: :trigger`, here's an example:\n\n```\nQ) LFXX/QRTTT/IV/BO /W /000/035/4708N00029E010\n        ^  ^^\n```\n\nNote: Trigger NOTAM are never published as series `T`.\n\n### Schedules\n\nFor compatibility, schedule dates and times are expressed using the corresponding classes from the [AIXM gem](https://rubygems.org/gems/aixm):\n\n* [Date](https://www.rubydoc.info/gems/aixm/AIXM/Schedule/Date)\n* [Day](https://www.rubydoc.info/gems/aixm/AIXM/Schedule/Day)\n* [Time](https://www.rubydoc.info/gems/aixm/AIXM/Schedule/Time)\n\nRaw and parsed NOTAM schedule times differ in how the \"end of day\" is encoded:\n\nNOTAM  | Beginning of Day | End of Day | Remarks\n-------|------------------|------------|--------\nRaw    | `\"0000\"`         | `\"2359\"`   | `\"2400\"` is considered illegal\nParsed | `00:00`          | `24:00`    | the Ruby way\n\n### References\n\n* [ICAO Doc 8126: Aeronautical Information Services Manual](https://www.icao.int/NACC/Documents/eDOCS/AIM/8126_unedited_en%20Jul2021.pdf)\n* [ICAO Doc 10066: Aeronautical Information Management](https://ffac.ch/wp-content/uploads/2020/11/ICAO-Doc-10066-Aeronautical-Information-Management.pdf)\n* [EUROCONTROL Guidelines Operating Procedures AIS Dynamic Data (OPADD)](https://www.eurocontrol.int/sites/default/files/2021-07/eurocontrol-guidelines-opadd-ed4-1.pdf)\n* [NOTAM Q Codes](https://www.faa.gov/air_traffic/publications/atpubs/notam_html/appendix_b.html)\n* [NOTAM Contractions](https://www.notams.faa.gov/downloads/contractions.pdf)\n* [NOTAM format cheat sheet](http://vat-air.dk/files/ICAO%20NOTAM%20format.pdf)\n* [Introduction on Wikipedia](https://en.wikipedia.org/wiki/NOTAM)\n\n## Translations\n\nYou find the translations for each available language in `lib/locales/`. Additional translations are very welcome provided you have sufficient aeronautical background knowledge.\n\nPlease [create a translation request issue](https://github.com/svoop/notam/issues), then duplicate the `lib/locales/en.yml` reference language file and translate it.\n\n## Tests and Fixtures\n\nThe test suite may run against live NOTAM depending on whether and how you set the `SPEC_SCOPE` environment variable:\n\n```\nexport SPEC_SCOPE=none       # don't run against any NOTAM fixtures (default)\nexport SPEC_SCOPE=W0214/22   # run against given NOTAM fixture only\nexport SPEC_SCOPE=all        # run against all NOTAM fixtures\nexport SPEC_SCOPE=all-fast   # run against all NOTAM fixtures but exit on the first failure\n```\n\nThe NOTAM fixtures are written to `spec/fixtures`, you can manage them using a Rake tasks:\n\n```\nrake --tasks fixtures\n```\n\n## Development\n\nTo install the development dependencies and then run the test suite:\n\n```\nbundle install\nbundle exec rake    # run tests once\nbundle exec guard   # run tests whenever files are modified\n```\n\nYou're welcome to [submit issues](https://github.com/svoop/notam/issues) and contribute code by [forking the project and submitting pull requests](https://docs.github.com/en/get-started/quickstart/fork-a-repo).\n\n## Trivia\n\nIn the early days, the acronym [NOTAM](https://en.wikipedia.org/wiki/NOTAM) ment \"Notice to Airmen\". As many women roam the skies these days as well, it has finally been redefined as \"Notice to Air Missions\".\n\n## License\n\nThe gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).\n","funding_links":["https://github.com/sponsors/svoop","https://donorbox.org/bitcetera"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsvoop%2Fnotam","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsvoop%2Fnotam","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsvoop%2Fnotam/lists"}