{"id":43251502,"url":"https://github.com/mtraver/environmental-sensor","last_synced_at":"2026-02-01T13:10:16.382Z","repository":{"id":57512998,"uuid":"82494228","full_name":"mtraver/environmental-sensor","owner":"mtraver","description":"Log temperature from an MCP9808 sensor to Google Cloud with Google Cloud IoT Core","archived":false,"fork":false,"pushed_at":"2025-12-01T06:54:09.000Z","size":779,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-12-03T08:45:33.562Z","etag":null,"topics":["appengine","cloud-iot-core","golang","google-cloud","iot","mcp9808","protobuf","protobuf3","pubsub","python","raspberry-pi"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mtraver.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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2017-02-19T22:29:09.000Z","updated_at":"2025-12-01T06:54:13.000Z","dependencies_parsed_at":"2024-03-17T19:24:48.713Z","dependency_job_id":"ea62d160-56e3-4694-99c3-17c604759965","html_url":"https://github.com/mtraver/environmental-sensor","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mtraver/environmental-sensor","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtraver%2Fenvironmental-sensor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtraver%2Fenvironmental-sensor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtraver%2Fenvironmental-sensor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtraver%2Fenvironmental-sensor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mtraver","download_url":"https://codeload.github.com/mtraver/environmental-sensor/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtraver%2Fenvironmental-sensor/sbom","scorecard":{"id":666759,"data":{"date":"2025-08-11","repo":{"name":"github.com/mtraver/environmental-sensor","commit":"a4e064a3f5d83ca57b83724064b1c87100a01a99"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.7,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Maintained","score":1,"reason":"2 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: GNU General Public License v3.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: containerImage not pinned by hash: MeasurementService.Dockerfile:2","Warn: containerImage not pinned by hash: MeasurementService.Dockerfile:21: pin your Docker image by updating debian:bookworm-slim to debian:bookworm-slim@sha256:b1a741487078b369e78119849663d7f1a5341ef2768798f7b7406c4240f86aef","Warn: containerImage not pinned by hash: Web.Dockerfile:2","Warn: containerImage not pinned by hash: Web.Dockerfile:22: pin your Docker image by updating debian:bookworm-slim to debian:bookworm-slim@sha256:b1a741487078b369e78119849663d7f1a5341ef2768798f7b7406c4240f86aef","Info:   0 out of   4 containerImage dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Vulnerabilities","score":8,"reason":"2 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GO-2022-0635","Warn: Project is vulnerable to: GO-2022-0646"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-21T18:19:03.307Z","repository_id":57512998,"created_at":"2025-08-21T18:19:03.307Z","updated_at":"2025-08-21T18:19:03.307Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28978910,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-01T12:13:08.691Z","status":"ssl_error","status_checked_at":"2026-02-01T12:13:08.356Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["appengine","cloud-iot-core","golang","google-cloud","iot","mcp9808","protobuf","protobuf3","pubsub","python","raspberry-pi"],"created_at":"2026-02-01T13:10:15.333Z","updated_at":"2026-02-01T13:10:16.378Z","avatar_url":"https://github.com/mtraver.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# MCP9808 Temperature Logger\n\n[![GoDoc](https://godoc.org/github.com/mtraver/environmental-sensor?status.svg)](https://godoc.org/github.com/mtraver/environmental-sensor)\n[![Go Report Card](https://goreportcard.com/badge/github.com/mtraver/environmental-sensor)](https://goreportcard.com/report/github.com/mtraver/environmental-sensor)\n\nLog temperature from an [MCP9808 sensor](https://www.adafruit.com/product/1782)\nconnected to a Raspberry Pi.\n\nSend temperature to [Google Cloud IoT Core](https://cloud.google.com/iot-core/),\nwhich can then be saved and plotted using the web app in the [web](web) directory.\nRunning `make` will build all binaries locally. Running `make web-image` will\nbuild a Docker image that can be deployed to Cloud Run to serve the web app.\n\nRun the `iotcorelogger` binary on the Raspberry Pi:\n\n```sh\nmake\n\n# Example config.pb.json\n# {\n#   \"supported_sensors\": [\"mcp9808\"],\n#\n#   \"jobs\": [\n#     {\n#       \"cronspec\": \"0 */2 * * * *\",\n#       \"operation\": \"SENSE\",\n#       \"sensors\": [\"mcp9808\"]\n#     }\n#   ]\n# }\n\n# Example device.json:\n# {\n#   \"project_id\": \"my-gcp-project\",\n#   \"registry_id\": \"my-iot-core-registry\",\n#   \"device_id\": \"my-device\",\n#   \"ca_certs_path\": \"roots.pem\",\n#   \"priv_key_path\": \"my-device.pem\",\n#   \"region\": \"us-central1\"\n# }\n./out/iotcorelogger -config config.pb.json -gcp-device device.json\n```\n\nThe config file sets up the sensors and schedules jobs using cron syntax, and\nthe device file specifies how to connect to IoT Core's MQTT broker to report\ntelemetry.\n\n## Prerequisites\n\n  - **Wire up the hardware.** Adafruit have a nice tutorial:\nhttps://learn.adafruit.com/mcp9808-temperature-sensor-python-library/overview\n  - **Enable I\u003csup\u003e2\u003c/sup\u003eC on your board.** For Raspberry Pi,\nthis can be done with `raspi-config`. You'll find the \"I2C\" option under\neither \"Advanced Options\" or \"Interfacing Options\".\n\n## Setting up Google Cloud IoT Core logging\n\n### Google Cloud setup\n\nThe scripts at https://github.com/mtraver/provisioning are useful for creating\nthe CA key and cert and device-specific keys and certs described below.\n\n- Create an IoT Core registry.\n  The [IoT Core quickstart](https://cloud.google.com/iot/docs/quickstart)\n  provides more info. The registry includes:\n  - A Pub/Sub topic for telemetry (you'll need to create the topic if it\n    doesn't already exist)\n  - A Pub/Sub topic for state (you'll need to create the topic if it\n    doesn't already exist)\n  - A CA cert for verifying device certs. This can be self-signed.\n- Add devices to the registry. This requires a device-specific cert that chains\n  to the CA cert. The key and cert can be made with the scripts in the repo\n  linked above. Heed the information there about key handling and about the\n  device ID (the device ID you use when making the cert must be the same as the\n  one you set when adding the device to the registry).\n- Create a subscription to the registry's telemetry topic. Configure it to\n  push to the `/push-handlers/telemetry` endpoint of the web app.\n  This is how IoT Core is tied to the web app.\n\nThe end-to-end flow is like this:\n1. A device sends a payload (in this case a protobuf; see\n   [measurement.proto](measurement.proto)) to IoT Core.\n2. IoT Core publishes the payload as a Pub/Sub message to the registry's\n   telemetry Pub/Sub topic.\n3. Pub/Sub pushes the message to the web app's endpoint, as configured in\n   the subscription to the topic.\n4. The web app receives the request, decodes the payload, and writes\n   it to the database.\n\n### Client program\n\nThe program in [cmd/iotcorelogger](cmd/iotcorelogger) runs on the Raspberry Pi\nand sends data to Google Cloud IoT Core. [cmd/README](cmd/README)\nhas information on building and configuring `iotcorelogger`.\n\nTODO(mtraver) add info on systemd config\n\n## Running and deploying the web app\n\n### Environment variables\n\nThe web app expects the following environment variables to be set. Define them\nin a file called `env` and the `make run-web` command below will pick them up.\n\nIn production, you'll need to make sure that they are available to the container\nvia env var config, secrets config, or whatever other method you like.\n\nTODO(mtraver) add descriptions of the env vars\n\n- `PUBSUB_VERIFICATION_TOKEN`\n- `PUBSUB_AUDIENCE`\n- `INFLUXDB_SERVER`\n- `INFLUXDB_TOKEN`\n- `INFLUXDB_ORG`\n- `INFLUXDB_BUCKET`\n\nFor local development you'll need to set `GOOGLE_CLOUD_PROJECT` to your GCP\nproject ID. In production on Cloud Run it's fetched automatically.\n\nFor local development you'll also want to put a key for a service account that\nallows reading from Google Cloud Datastore and Google Cloud IoT Core in a dir\ncalled `keys` and then set the `GOOGLE_APPLICATION_CREDENTIALS` env var, e.g.:\n\n```sh\nGOOGLE_APPLICATION_CREDENTIALS=/keys/my-key.json\n```\n\nIn production `GOOGLE_APPLICATION_CREDENTIALS` isn't necessary because the service\nwill have the proper permissions granted to it.\n\n### Build and run locally\n\nDid you make your `env` file and put your service account key in `keys`?\nDo that first (see above).\n\n```sh\nPROJECT=my-gcp-project-id REPO=my-artifact-repository-repo-name make web-image\nPROJECT=my-gcp-project-id REPO=my-artifact-repository-repo-name make run-web\n```\n\n### Build on Google Cloud Build\n\nThis will build the image remotely and push it to Google Artifact Repository.\n\n```sh\nPROJECT=my-gcp-project-id REPO=my-artifact-repository-repo-name make web-image-remote\n```\n\n### Deploying to Cloud Run\n\nDeploy the image built with `make web-image-remote` to Cloud Run and make sure\nthat the env vars (aside from `GOOGLE_CLOUD_PROJECT` and `GOOGLE_APPLICATION_CREDENTIALS`)\nare made available to it.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmtraver%2Fenvironmental-sensor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmtraver%2Fenvironmental-sensor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmtraver%2Fenvironmental-sensor/lists"}