{"id":21388108,"url":"https://github.com/grisp/grisp_connect","last_synced_at":"2026-02-13T20:08:03.197Z","repository":{"id":234717265,"uuid":"449743136","full_name":"grisp/grisp_connect","owner":"grisp","description":"GRiSP.io client application","archived":false,"fork":false,"pushed_at":"2025-01-21T15:30:11.000Z","size":364,"stargazers_count":1,"open_issues_count":3,"forks_count":0,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-01-23T13:51:27.562Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Erlang","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/grisp.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":"2022-01-19T15:16:55.000Z","updated_at":"2024-11-18T10:35:13.000Z","dependencies_parsed_at":"2024-05-10T11:25:27.206Z","dependency_job_id":"bbd3e2d2-e54c-4861-b33d-616015730cb4","html_url":"https://github.com/grisp/grisp_connect","commit_stats":null,"previous_names":["grisp/grisp_connect"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grisp%2Fgrisp_connect","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grisp%2Fgrisp_connect/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grisp%2Fgrisp_connect/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grisp%2Fgrisp_connect/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/grisp","download_url":"https://codeload.github.com/grisp/grisp_connect/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":236641474,"owners_count":19181874,"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":[],"created_at":"2024-11-22T12:15:58.919Z","updated_at":"2026-02-13T20:08:03.184Z","avatar_url":"https://github.com/grisp.png","language":"Erlang","funding_links":[],"categories":[],"sub_categories":[],"readme":"# grisp_connect\n\nGRiSP.io Client Library for GRiSP. This library enables secure communication\n between your GRiSP2 board and the [GRiSP.io](https://grisp.io) services using\n Mutual TLS (mTLS). To get started, add this application as a dependency in your\n GRiSP2 project.\n\n⚠️ **Note:** If you plan to use the API calls related to `grisp_updater_grisp2`,\nmake sure to add `grisp_updater_grisp2` as a dependency in your project as well.\n\n## Table of content\n\n- [grisp\\_connect](#grisp_connect)\n  - [Table of content](#table-of-content)\n  - [Usage](#usage)\n    - [Option 1. Use the `rebar3_grisp` plugin](#option-1-use-the-rebar3_grisp-plugin)\n    - [Option 2. Add `grisp_connect` Manually to your Application](#option-2-add-grisp_connect-manually-to-your-application)\n  - [Further Steps](#further-steps)\n    - [Check whether the board is connected](#check-whether-the-board-is-connected)\n    - [Link your Device to your GRiSP.io Account](#link-your-device-to-your-grispio-account)\n    - [Troubleshooting:](#troubleshooting)\n    - [Need to Unlink a Device?](#need-to-unlink-a-device)\n  - [Environment Options](#environment-options)\n    - [`connect`](#connect)\n    - [`ntp`](#ntp)\n    - [`ws_request_timeout`](#ws_request_timeout)\n    - [`ws_ping_timeout`](#ws_ping_timeout)\n    - [`logs_interval`](#logs_interval)\n    - [`logs_batch_size`](#logs_batch_size)\n  - [grisp\\_keychain](#grisp_keychain)\n    - [Use a specific backend](#use-a-specific-backend)\n    - [Development options](#development-options)\n      - [`allow_expired_certs`](#allow_expired_certs)\n  - [See all Logs on GRiSP.io](#see-all-logs-on-grispio)\n  - [Development](#development)\n    - [Local Development](#local-development)\n    - [Development on GRiSP Hardware](#development-on-grisp-hardware)\n    - [Production on GRiSP Hardware](#production-on-grisp-hardware)\n\n## Usage\n\n### Option 1. Use the `rebar3_grisp` plugin\n\nThe `configure` method of the `rebar3_grisp` version \u003e= 2.6.0 will add `grisp_connect` with the needed configurations to your GRiSP application. See [GRiSP Wiki/Use-your-GRiSP-2-board-with-GRiSP.io](https://github.com/grisp/grisp/wiki/Use-your-GRiSP-2-board-with-GRiSP.io).\n\n### Option 2. Add `grisp_connect` Manually to your Application\n\nAdd\n\n```erlang\n{dep, [{grisp_connect, \"1.0.0\"}]}\n```\n\nto your `rebar.config` file.\n\nIf you still need to link your device configure the device linking token in your `sys.config`:\n\n```erlang\n[ {grisp_connect, [\n    {device_linking_token, \u003c\u003c\"...\"\u003e\u003e}\n]}].\n```\n\nYou can find your device linking token on [GRiSP.io/grisp_manager](https://grisp.io/grisp_manager) under \"How to Link a Device/Option 2: Manual Linking (Ethernet / Wifi)\".\n\nYou can also skip this configuration and insert the token manually later.\n\n## Further Steps\n\n### Check whether the board is connected\n\n```erlang\n\u003e grisp_connect:is_connected().\ntrue\n\u003e grisp_connect:ping().\n{ok,\u003c\u003c\"pong\"\u003e\u003e}\n```\n\n### Link your Device to your GRiSP.io Account\n\n```erlang\n\u003e grisp_connect:link_device(\u003c\u003c\"...\"\u003e\u003e).\n```\n\nOr, if your token is configured in the environment:\n\n```erlang\n\u003e grisp_connect:link_device().\n```\n\n### Troubleshooting:\n`grisp_connect:link_device` may fail with the following errors.\n\n**Common Errors:**\n\n- `token_expired`: regenerate one from the web page\n- `invalid_token`: please double check you typed it correctly\n- `token_undefined`: you called `grisp_connect:link_device/0` without setting `device_linking_token`\n- `disconnected`: check that your board can connect\n- `device_already_linked`: please do not steal GRiSP boards :smirk:\n  if you need to unlink a GRiSP board see below...\n\n### Need to Unlink a Device?\n\nWe currently do not expose a public API to unlink a Device. Please reach out to us for assistance.\n\nIf you encounter any problems or have questions, don't hesitate to contact [support](mailto:grisp@stritzinger.com). Happy coding!\n\n## Environment Options\n\n### `connect`\n\nThis option is set to `true` as default. Set it to `false` to prevent automatic connection to GRiSP.io on boot.\nIn such case the state machine that maintains the connection can be started manually using `grisp_connect_client:connect()`.\n\n### `ntp`\n\nAn optional NTP client can be started using option `{ntp, true}`.\nSuch client is disabled by default (`{ntp, false}`), and is not required to\nauthenticate with GRiSP.io. The client sets the time using\n`grisp_rtems:clock_set/1`.\nThe default NTP servers to use can be overridden by setting the `grisp_connect`\noption: `{ntp_servers, [\"ntp1.server.foo\", \"ntp2.server.foo\"]}`. For every NTP\nrequests, a server address will be picked randomly from the list.\nThe default refresh period in seconds can be overridden by setting the\n`grisp_connect` option: `{ntp_refresh_period, 1024}`.\n\n### `ws_request_timeout`\n\nAccepts an integer that represents time in milliseconds, default value is `5_000`.\nAllows to tweak the timeout of each API request going through the websocket.\n\n### `ws_ping_timeout`\nAccepts an integer that represents time in milliseconds, default value is `60_000`.\nAllows to tweak the timeout between expected ping frames from the server.\nIf the timeout is exceeded, the socket is closed and a new connection is attempted.\n\n### `logs_interval`\n\nAccepts an integer that represents time in milliseconds, default value is `2_000`.\nSets the intervall between each log batch dispatch to grisp.io.\n\n### `logs_batch_size`\n\nAccepts an integer that represents the maximum number of logs that can be batched together, default value is `100`.\n\n## grisp_keychain\n\nTo be able to connect securely with our backend you need to correctly setup certificates and keys access through `grisp_keychain` enviroment.\n\nThis can variate greatly depending on the platfrom and usecase of your deployment.\nTo correctly setup a new project, please use our [rebar3_grisp plugin](https://github.com/grisp/rebar3_grisp?tab=readme-ov-file#create-new-application).\n\nTLS settings are fetched through the [grisp_keychain app](https://github.com/grisp/grisp_keychain). This app defaults to use a simple file filesystem access and requires additional informations to locate the certificates.\n\nIn this example we use `grisp_keychain` alone. Relying on free filesystem access.\nWe are using certifi CAs and a device certificate and key we have in priv.\n\n```erlang\n    % Example sys.config\n    [\n        ...\n        {grisp_keychain, [\n            {api_module, grisp_keychain_filesystem}, % default\n            {tls_server_trusted_certs_cb, {certifi, cacerts, []}},\n            {client_certs, {priv, myapp, \"certs/device.pem\"}},\n            {client_key, {priv, myapp, \"certs/device.key\"}}\n        ]}\n    ]\n```\n\n### Use a specific backend\n\nFor production usecases we are developing backends to securely access certificates and keys.\n\nFor example: if you are using GRiSP2 you will need `grisp_cryptoauth` to use secrets held by the secure element. See the [grisp_cryptoauth TLS options](https://github.com/grisp/grisp_cryptoauth?tab=readme-ov-file#configuring-tls-options) to customize them. A simple configuration that uses secure element certs and `certifi` as CA provider will look like this:\n\n```erlang\n\n    % Example sys.config\n    [\n        ...\n        {grisp_keychain, [\n            {api_module, grisp_cryptoauth}\n        ]},\n        {grisp_cryptoauth, [\n            {tls_server_trusted_certs_cb, {certifi, cacerts, []}}\n        ]}\n    ]\n```\nNote: we do not depend on `certifi`, make sure it is added to your deps in case you want to use it.\n\n### Development options\n\n#### `allow_expired_certs`\n\n`grisp_connect` will ignore `cert_expired` errors during certificate path validation. This should only be used for development. Default is `false`.\n\n```erlang\n    % Example sys.config\n    [\n        ...\n        {grisp_keychain, [\n            ...\n            {allow_expired_certs, true},\n            ...\n        ]}\n    ]\n```\n\n## See all Logs on GRiSP.io\n\nOnce this app is started, it forwards all logs to GRiSP.io without the need of setting up anything. The only logs that we do not catch are the ones generated before `grisp_connect` boots.\nIf you want to see ALL logs, even from applications that boot before `grisp_connect`, you need to add the log handler in the kernel configuration and disable the one defined in the `grisp_connect` application configuration. This involves changing the `kernel` and `grisp_connect` app configuration settings in your sys.config file.\n\nYou can copy paste these settings:\n\n```erlang\n% sys.config\n[\n    {kernel, [\n        {logger_level, notice},\n        {logger, [\n            {handler, default, logger_std_h, #{\n                level =\u003e notice,\n                filter_default =\u003e log,\n                filters =\u003e [\n                    % Filter out supervisor progress reports so TLS certificates\n                    % are not swamping the console if the level is set to info...\n                    {disable_progress, {fun logger_filters:progress/2, stop}}\n                ]\n            }}\n            {handler, grisp_connect_log_handler,  grisp_connect_logger_bin, #{\n                level =\u003e notice,\n                filter_default =\u003e log,\n                formatter =\u003e {grisp_connect_logger_bin, #{}},\n                filters =\u003e [\n                    % Filter out supervisor progress reports so TLS certificates\n                    % are not swamping grisp.io if level is set to info...\n                    {disable_progress, {fun logger_filters:progress/2, stop}}\n                ]\n             }\n            }\n        ]}\n    ]},\n    {grisp_connect, [\n        % Disable the log handler defined in grisp_connect application default\n        % configuration, as it was explicitly started in kernel configuration\n        % in order to catch the log entries before grisp_connect is started.\n        {logger, []}\n        ]}\n    ]}\n].\n```\n\nTo simplify the log on the device while still sending full log reports to\ngriso.io, use grisp_connect_log log formatter with single-line in the default\nlog handler:\n\n```\n            {handler, default, logger_std_h, #{\n                level =\u003e notice,\n                formatter =\u003e {grisp_connect_log, #{\n                    legacy_header =\u003e false,\n                    single_line =\u003e true,\n                    description_only =\u003e true\n                }},\n                filter_default =\u003e log,\n                filters =\u003e [\n                    % Filter out supervisor progress reports so TLS certificates\n                    % are not swamping the console if the level is set to info...\n                    {disable_progress, {fun logger_filters:progress/2, stop}}\n                ]\n            }}\n```\n\n## Development\n\n### Local Development\n\nAdd an entry in your local hosts file so the domain www.seawater.local points\nto your local development server.\n\nMake sure you have the proper certificates under `prinv/server` and `priv/client`. Refer to the backend private docs on how to generate the certificates.\n\nStart a local development shell:\n\n    rebar3 as local shell\n\nRun tests:\n\n    rebar3 ct\n\nTo run the tests it might be necessary that you clean out the _build folder in case you compiled with another profile before:\n\n    rm -rf _build\n\n### Development on GRiSP Hardware\n\nAdd an entry in the grisp hosts file so the domain www.seawater.local points\nto your local development server.\n\ne.g. using `ifconfig` command (MacOS and older linux):\n\n    echo \"$(ifconfig | grep 'inet ' | grep -v 127.0.0.1 | awk '{ print $2 }' | head -n 1) www.seawater.local\" \u003e\u003e grisp/default/common/deploy/files/etc/hosts\n]\ne.g. using `ip` command (Newer linux):\n\n    echo \"$(ip addr show | grep 'inet ' | grep -v 127.0.0.1 | awk '{print $2}' | cut -d/ -f1 | head -n 1) www.seawater.local\" \u003e\u003e grisp/default/common/deploy/files/etc/hosts\n\nTo deploy the release, configure rebar3_grisp's deploy configuration in\nrebar.config and then run:\n\n    rebar3 as dev grisp deploy\n\n### Production on GRiSP Hardware\n\nTo deploy on GRiSP hardware for production, configure rebar3_grisp's deploy\nconfiguration in rebar.config and then run:\n\n    rebar3 as prod grisp deploy\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgrisp%2Fgrisp_connect","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgrisp%2Fgrisp_connect","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgrisp%2Fgrisp_connect/lists"}