{"id":16726875,"url":"https://github.com/tpitale/coap_ex","last_synced_at":"2025-10-10T12:15:41.855Z","repository":{"id":55604705,"uuid":"144346276","full_name":"tpitale/coap_ex","owner":"tpitale","description":"CoAP Server/Client with support for Phoenix","archived":false,"fork":false,"pushed_at":"2024-08-20T15:20:14.000Z","size":226,"stargazers_count":19,"open_issues_count":27,"forks_count":3,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-10-04T02:58:47.334Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Elixir","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/tpitale.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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,"publiccode":null,"codemeta":null}},"created_at":"2018-08-11T01:35:45.000Z","updated_at":"2025-04-01T13:27:14.000Z","dependencies_parsed_at":"2024-10-28T11:34:33.068Z","dependency_job_id":"90921386-ff65-4bd9-840a-7d3690578a8c","html_url":"https://github.com/tpitale/coap_ex","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/tpitale/coap_ex","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tpitale%2Fcoap_ex","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tpitale%2Fcoap_ex/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tpitale%2Fcoap_ex/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tpitale%2Fcoap_ex/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tpitale","download_url":"https://codeload.github.com/tpitale/coap_ex/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tpitale%2Fcoap_ex/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279003899,"owners_count":26083639,"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","status":"online","status_checked_at":"2025-10-10T02:00:06.843Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":[],"created_at":"2024-10-12T22:54:51.069Z","updated_at":"2025-10-10T12:15:41.839Z","avatar_url":"https://github.com/tpitale.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"# CoAP\n\nServer and Client for building and interacting with Constrained Application Protocol.\n\nAllows using Plug and Phoenix or a standalone module.\n\n## Installation\n\nIf [available in Hex](https://hex.pm/docs/publish), the package can be installed\nby adding `coap` to your list of dependencies in `mix.exs`:\n\n```elixir\ndef deps do\n  [\n    {:coap_ex, \"~\u003e 0.1.0\"}\n  ]\nend\n```\n\nDocumentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)\nand published on [HexDocs](https://hexdocs.pm). Once published, the docs can\nbe found at [https://hexdocs.pm/coap](https://hexdocs.pm/coap).\n\n## Setup\n\nMake a new router and endpoint:\n\n```\ndefmodule MyApp.Coap.Router do\n  use MyApp.Web, :router\nend\n```\n\n```\ndefmodule MyApp.Coap.Endpoint do\n  use Phoenix.Endpoint, otp_app: :my_app\n  plug(MyApp.Coap.Router)\nend\n```\n\nIn phoenix `config.exs`:\n\n```\nconfig :my_app, MyApp.Coap.Endpoint,\n  http: false, https: false, server: false,\n  coap: [port: 5683]\n```\n\n**Note**: if you have control of both client and server, as in an IoT deployment,\nyou may wish to adjust configuration for `ack_timeout` and `processing_delay`.\nThis is allowed, but should be used with extreme caution as it exists outside\nthe boundaries of the CoAP specification.\n\n```\nconfig :my_app, MyApp.Coap.Endpoint,\n  http: false, https: false, server: false,\n  coap: [port: 5683, ack_timeout: 5000, processing_delay: 4500]\n```\n\nIn `lib/my_app.ex` add supervisor and listener for the endpoint:\n\n```\nchildren = [\n  MyApp.Coap.Endpoint,\n  {CoAP.Phoenix.Listener, [MyApp.Coap.Endpoint]}\n]\n```\n\n# Client #\n\nSimple client usage:\n\n```\nCoAP.Client.get(\"coap://localhost:5683/api/healthcheck\")\n```\n\n# Telemetry #\n\nCoap_ex emits telemetry events for data sent and received, block transfers, and other connection-releated events.  To consume them, attach a handler in your app startup like so:\n\n```\n:telemetry.attach_many(\n  \"myapp-coap-ex-connection\",\n  [\n    [:coap_ex, :connection, :block_sent],\n    [:coap_ex, :connection, :block_received],\n    [:coap_ex, :connection, :connection_started],\n    [:coap_ex, :connection, :connection_ended],\n    [:coap_ex, :connection, :data_sent],\n    [:coap_ex, :connection, :data_received],\n    [:coap_ex, :connection, :re_tried],\n    [:coap_ex, :connection, :timed_out]\n  ],\n  \u0026MyHandler.handle_event/4,\n  nil\n)\n```\n\nEach connection can be tagged when the connection is created, and this tag will be passed to the telemetry handler.  This makes it possible to monitor a single connection among many connections. The tag can be any value.\n\nTo tag a client connection, pass a tag in the request options:\n\n```\nCoAP.Client.request(\n  :con,\n  method,\n  url,\n  request_payload,\n  %{retries: retries, timeout: @wait_timeout, ack_timeout: timeout, tag: tag}\n)\n ```\n \n To tag a server connection if using Phoenix:\n \n ```\n # in phoenix controller\n CoAP.Phoenix.Conn.tag(conn, tag)\n ```\n\n# TODO:\n\n* [x] handle multiple parts for some headers, like \"Uri-Path\"\n* [x] coap client, ala httpoison\n* [x] message_id is started at a random int and incremented for a single connection\n* [x] block-wise transfer\n* [ ] handle timeouts and retries of block-wise transfers\n* [ ] accept block-wise transfer controls over size\n* [ ] respect block-wise transfer controls over size\n* [x] respect block-wise transfer controls over block number\n* [ ] instrumentation of listener/adapter/handler in some way, using phx tools\n* [ ] support coaps scheme\n* [x] hostname support?\n\n`./coap-client.sh -m put coap://127.0.0.1/resource -e data`\n`nc -l 5683 -u | xxd`\n\n```\nmessage = \u003c\u003c0x44, 0x03, 0x31, 0xfc, 0x7b, 0x5c, 0xd3, 0xde, 0xb8, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x77, 0x68, 0x6f, 0x3d, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0xff, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64\u003e\u003e\nCoAP.Message.decode(message)\n```\n\n`coap_content(payload: \"data\")` comes from using defrecord from gen_coap, right now.\n\n`:coap_client.request(:get, 'coap://127.0.0.1:5683/api/?who=world', coap_content(payload: \"payload\"), [{:uri_host, \"localhost\"}])`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftpitale%2Fcoap_ex","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftpitale%2Fcoap_ex","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftpitale%2Fcoap_ex/lists"}