{"id":29801485,"url":"https://github.com/galihru/githubiot","last_synced_at":"2026-06-15T08:31:23.686Z","repository":{"id":282089381,"uuid":"938195883","full_name":"galihru/githubiot","owner":"galihru","description":"Library enables IoT devices based on ESP8266 or ESP32 microcontrollers to use GitHub as a data storage backend. This innovative approach eliminates the need for dedicated database servers while providing versioning capabilities, web accessibility, and integration with existing GitHub workflows. ","archived":false,"fork":false,"pushed_at":"2025-06-29T10:22:06.000Z","size":51,"stargazers_count":9,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-02-23T11:16:02.278Z","etag":null,"topics":["arduino-ide","arduino-library","esp32","esp8266","github-actions","iot","iot-application","iot-platform","webapp"],"latest_commit_sha":null,"homepage":"https://github.com/4211421036/githubiot","language":"C++","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/galihru.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-02-24T15:15:53.000Z","updated_at":"2025-12-28T06:29:33.000Z","dependencies_parsed_at":null,"dependency_job_id":"317e0558-39d4-4275-aac3-804f27e9aa6f","html_url":"https://github.com/galihru/githubiot","commit_stats":null,"previous_names":["4211421036/githubiot","galihru/githubiot"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/galihru/githubiot","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/galihru%2Fgithubiot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/galihru%2Fgithubiot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/galihru%2Fgithubiot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/galihru%2Fgithubiot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/galihru","download_url":"https://codeload.github.com/galihru/githubiot/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/galihru%2Fgithubiot/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34355157,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-15T02:00:07.085Z","response_time":63,"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":["arduino-ide","arduino-library","esp32","esp8266","github-actions","iot","iot-application","iot-platform","webapp"],"created_at":"2025-07-28T09:46:02.334Z","updated_at":"2026-06-15T08:31:23.665Z","avatar_url":"https://github.com/galihru.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Documentation and Usage Guide GitHub IoT Arduino Module\n*Version 1.0.0 - February 24, 2025*\n\n\u003cp align=\"center\"\u003e\n  \u003cimg style=\"width: -webkit-fill-available;\"src=\"https://galihru.github.io/githubiotpy/img/GitHub%20IoT%20Logo.png\" alt=\"GitHubIoT Logo\"\u003e\n\u003c/p\u003e\n\n## Introduction\n\nThe `githubiot` library enables IoT devices based on ESP8266 or ESP32 microcontrollers to use GitHub as a data storage backend. This innovative approach eliminates the need for dedicated database servers while providing versioning capabilities, web accessibility, and integration with existing GitHub workflows.\n\nThis library handles all aspects of GitHub API communication, including authentication, file retrieval, content encoding/decoding, and update operations, allowing developers to focus on their IoT application rather than backend infrastructure.\n\n---\n\n## Table of Contents\n1. [Introduction](#introduction)\n2. [Features](#features)\n3. [Dependencies](#dependencies)\n4. [Installation](#installation)\n5. [Integration GitHub Action](#integration-github-action)\n7. [Library Components](#library-components)\n8. [API Reference](#api-reference)\n9. [Usage Examples](#usage-examples)\n10. [Technical Background](#technical-background)\n11. [Performance Considerations](#performance-considerations)\n12. [Troubleshooting](#troubleshooting)\n13. [Advanced Usage](#advanced-usage)\n14. [License](#license)\n\n---\n\n## Features\n\n- **GitHub Integration**: Store and retrieve data from GitHub repositories\n- **JSON Support**: Native handling of JSON data structures\n- **Cross-Platform**: Compatible with both ESP8266 and ESP32 devices\n- **Version Control**: Automatic handling of GitHub's SHA versioning\n- **Low Overhead**: Minimal memory and processing requirements\n- **Secure Authentication**: Support for GitHub token-based authentication\n- **Base64 Encoding**: Automatic handling of GitHub's content encoding requirements\n\n---\n\n## Dependencies\n\nThis library requires the following dependencies:\n\n- **Arduino Core** (ESP8266 or ESP32)\n- **ArduinoJson** (v6.x or later)\n- **base64** library\n- **WiFi** library (included in ESP cores)\n- **HTTPClient** library (included in ESP cores)\n\n---\n\n## Installation\n\n### Installation by Search Arduino IDE\n\n1. In the Arduino IDE, navigate to Library Manager \u003e `GitHubIoT`\n2. Klik \u003cmark\u003eINSTALL\u003c/mark\u003e\n3. Restart the Arduino IDE\n\n### Manual Installation\n\n1. Download the library as a ZIP file from the [GitHub repository](https://github.com/username/githubiot)\n2. In the Arduino IDE, navigate to Sketch \u003e Include Library \u003e Add .ZIP Library\n3. Select the downloaded ZIP file\n4. Restart the Arduino IDE\n\n### Using Library Manager\n\n1. Open the Arduino IDE\n2. Navigate to Sketch \u003e Include Library \u003e Manage Libraries\n3. In the search box, type \"githubiot\"\n4. Find the library in the list and click \"Install\"\n\n### Installing Dependencies\n\nMake sure to install all required dependencies using the Arduino Library Manager.\n\n---\n\n## Integration GitHub Action\n\u003e [!NOTE]\n\u003e This module integration with GitHub Action Workflow. Please README Documentation at Repository [IoT GitHub](https://github.com/galihru/iotgithub?tab=readme-ov-file)\n\n### Usage Integration it\n\u003e [!IMPORTANT]\n\u003e 1. Go to your repository settings, then select the Action menu then select the General menu after that select Read and write permissions The workflow has read and write permissions in the repository for all scopes in the Workflow permissions section.\n\n2. Copy and paste the following snippet into your .yml file. Detail by [IoT GitHub Marketplace](https://github.com/marketplace/actions/generate-iot-dashboard)\n3. You can see detail snippet .yml file below\n\n```yml\n- name: Generate IoT Dashboard\n  uses: galihru/iotgithub@v1.0.1\n  with:\n    json_filename: 'data.json'\n    html_filename: 'index.html'\n    css_filename: 'styles.css'\n    site_title: 'My IoT Dashboard'\n    chart_title: 'IoT Data Chart'\n- name: Commit and push changes\n  run: |\n    git config --global user.name \"GitHub Actions\"\n    git config --global user.email \"actions@github.com\"\n    git add .\n    if git commit -m \"Auto-generated IoT dashboard files\"; then\n      git push\n    else\n      echo \"No changes to commit.\"\n    fi\n```\n\n---\n\n## Library Components\n\nThe library consists of two main files:\n\n1. **githubiot.h**: Header file defining the class interface\n2. **githubiot.cpp**: Implementation file containing the method definitions\n\n### Class Structure\n\n```cpp\nclass githubiot {\npublic:\n    githubiot(const char* token, const char* repoUrl);\n    String get_current_sha();\n    void upload_to_github(DynamicJsonDocument doc, String\u0026 last_sha);\nprivate:\n    const char* _token;\n    const char* _repo_url;\n    String _last_sha;\n};\n```\n\n---\n\n## API Reference\n\n### Constructor\n\n```cpp\ngithubiot::githubiot(const char* token, const char* repo_url)\n```\n\nCreates a new instance of the githubiot class.\n\n**Parameters:**\n- `token`: GitHub authentication token with 'Bearer ' prefix\n- `repo_url`: GitHub API URL for the file to be updated\n\n**Example:**\n```cpp\nconst char* token = \"Bearer ghp_xxxxxxxxxxxxxxxxxxxx\";\nconst char* repo_url = \"https://api.github.com/repos/username/repo/contents/data.json\";\ngithubiot iot_module(token, repo_url);\n```\n\n### Get Current SHA\n\n```cpp\nString githubiot::get_current_sha()\n```\n\nRetrieves the current SHA hash of the file from GitHub.\n\n**Returns:**\n- String containing the SHA hash, or empty string if the operation failed\n\n**Example:**\n```cpp\nString sha = iot_module.get_current_sha();\nif (sha != \"\") {\n    Serial.println(\"Current SHA: \" + sha);\n} else {\n    Serial.println(\"Failed to get SHA\");\n}\n```\n\n### Upload to GitHub\n\n```cpp\nvoid githubiot::upload_to_github(DynamicJsonDocument doc, String\u0026 last_sha)\n```\n\nUploads data to GitHub by updating the specified file.\n\n**Parameters:**\n- `doc`: ArduinoJson DynamicJsonDocument containing the data to upload\n- `last_sha`: Reference to the current SHA string (will be updated with the new SHA)\n\n**Example:**\n```cpp\nDynamicJsonDocument doc(1024);\ndoc[\"sensor\"] = \"temperature\";\ndoc[\"value\"] = 25.5;\ndoc[\"timestamp\"] = 1645729845;\n\nString sha = iot_module.get_current_sha();\niot_module.upload_to_github(doc, sha);\n```\n\n---\n\n## Usage Examples\n\n### Basic Data Logging\n\n```cpp\n#include \u003cgithubiot.h\u003e\n\n// Configuration\nconst char* ssid = \"WiFi_SSID\";\nconst char* password = \"WiFi_Password\";\nconst char* token = \"Bearer ghp_xxxxxxxxxxxxxxxxxxxx\";\nconst char* repo_url = \"https://api.github.com/repos/username/repo/contents/sensor_log.json\";\n\n// Initialize the module\ngithubiot iot_module(token, repo_url);\n\nvoid setup() {\n    Serial.begin(115200);\n    \n    // Connect to WiFi\n    WiFi.begin(ssid, password);\n    while (WiFi.status() != WL_CONNECTED) {\n        delay(1000);\n        Serial.print(\".\");\n    }\n    Serial.println(\"Connected to WiFi\");\n    \n    // Get current SHA\n    String sha = iot_module.get_current_sha();\n    \n    // Create data\n    DynamicJsonDocument doc(1024);\n    doc[\"device_id\"] = \"esp32_01\";\n    doc[\"readings\"][0][\"sensor\"] = \"temperature\";\n    doc[\"readings\"][0][\"value\"] = 24.5;\n    doc[\"readings\"][1][\"sensor\"] = \"humidity\";\n    doc[\"readings\"][1][\"value\"] = 65.2;\n    doc[\"timestamp\"] = 1645729845;\n    \n    // Upload to GitHub\n    iot_module.upload_to_github(doc, sha);\n    Serial.println(\"Data uploaded\");\n}\n\nvoid loop() {\n    // Add periodic data logging as needed\n    delay(3600000); // Update every hour\n}\n```\n\n### Time Series Data Collection\n\n```cpp\n#include \u003cgithubiot.h\u003e\n#include \u003cArduinoJson.h\u003e\n#include \u003ctime.h\u003e\n\n// Configuration\nconst char* ssid = \"WiFi_SSID\";\nconst char* password = \"WiFi_Password\";\nconst char* token = \"Bearer ghp_xxxxxxxxxxxxxxxxxxxx\";\nconst char* repo_url = \"https://api.github.com/repos/username/repo/contents/timeseries.json\";\nconst char* ntpServer = \"pool.ntp.org\";\n\n// Initialize the module\ngithubiot iot_module(token, repo_url);\n\nvoid setup() {\n    Serial.begin(115200);\n    \n    // Connect to WiFi\n    WiFi.begin(ssid, password);\n    while (WiFi.status() != WL_CONNECTED) {\n        delay(1000);\n        Serial.print(\".\");\n    }\n    Serial.println(\"Connected to WiFi\");\n    \n    // Initialize time\n    configTime(0, 0, ntpServer);\n}\n\nvoid loop() {\n    // Get current time\n    time_t now;\n    time(\u0026now);\n    \n    // Read sensor data\n    float temperature = readTemperature(); // Your sensor reading function\n    \n    // Get current SHA\n    String sha = iot_module.get_current_sha();\n    \n    // Create or update time series data\n    DynamicJsonDocument doc(2048);\n    \n    // If we have existing data, we need to parse it first\n    if (sha != \"\") {\n        // Here we would retrieve existing data and merge\n        // This example simply creates new data each time\n    }\n    \n    // Add new data point\n    JsonObject newReading = doc[\"readings\"].createNestedObject();\n    newReading[\"timestamp\"] = now;\n    newReading[\"temperature\"] = temperature;\n    \n    // Upload to GitHub\n    iot_module.upload_to_github(doc, sha);\n    Serial.println(\"Data uploaded\");\n    \n    // Wait before next reading\n    delay(900000); // 15 minutes\n}\n\nfloat readTemperature() {\n    // Implementation of your sensor reading\n    return 23.5; // Example value\n}\n```\n\n---\n\n## Technical Background\n\n### GitHub API Interaction\n\nThe library communicates with the GitHub API using HTTP requests. Each file in a GitHub repository has a unique SHA hash that changes when the file is modified. When updating a file, you must provide the current SHA to ensure you're updating the latest version.\n\nThe workflow follows this sequence:\n\n1. Retrieve the current file metadata (including SHA) via GET request\n2. Prepare the new content\n3. Encode the content in Base64 (GitHub requirement)\n4. Send a PUT request with the new content and current SHA\n5. Receive the updated file metadata (including new SHA)\n\n### JSON Data Format\n\nJSON (JavaScript Object Notation) is used as the data format due to its flexibility and widespread support. The ArduinoJson library provides efficient JSON processing on memory-constrained devices.\n\n### Base64 Encoding\n\nGitHub requires file content to be Base64 encoded in API requests. The encoding process converts binary data to ASCII text using the following transformation:\n\n$$ \\text{Base64}(M) = \\text{concat}(B_1, B_2, \\ldots, B_n) $$\n\nWhere each block $B_i$ is computed from 3 octets of the input message $M$:\n\n$$ B_i = \\text{enc}(M_{3i-2}, M_{3i-1}, M_{3i}) $$\n\nThe encoding function maps 3 bytes (24 bits) to 4 ASCII characters (6 bits each) according to the Base64 alphabet.\n\n### HTTP Status Codes\n\n\u003e [!NOTE]\n\u003e The library handles various HTTP status codes returned by the GitHub API:\n\n| Status Code | Description | Library Action |\n|-------------|-------------|----------------|\n| 200 (OK) | Request successful | Process response |\n| 401 (Unauthorized) | Invalid token | Return error |\n| 404 (Not Found) | File or repository not found | Return error |\n| 409 (Conflict) | SHA mismatch (file changed) | Return error |\n| 422 (Unprocessable Entity) | Validation failed | Return error |\n\n---\n\n## Performance Considerations\n\n### Memory Usage\n\nThe ArduinoJson library uses dynamic memory allocation. The size of the `DynamicJsonDocument` should be adjusted based on your data complexity:\n\n$$ \\text{requiredSize} \\approx \\text{jsonLength} \\times 1.1 + 10 $$\n\nFor ESP8266 devices with limited memory, consider:\n- Keeping JSON structures simple\n- Reducing the size of string literals\n- Processing data in smaller chunks\n\n### Network Performance\n\n\u003e [!CAUTION]\n\u003e GitHub API has rate limits:\n\u003e - Authenticated requests: 5,000 requests/hour\n\u003e - For optimal performance, limit update frequency to no more than once per minute\n\nThe average request-response cycle takes approximately 500-1500ms depending on network conditions.\n\n### Power Consumption\n\nTo optimize power consumption for battery-operated devices:\n- Use deep sleep between updates\n- Schedule updates at regular intervals\n- Implement error backoff strategy\n\n---\n\n## Troubleshooting\n\n### Common Issues and Solutions\n\n#### \"Failed to get SHA\"\n\n**Possible causes:**\n\u003e [!IMPORTANT]\n\u003e - Invalid GitHub token\n\u003e - Incorrect repository URL\n\u003e - File doesn't exist yet\n\u003e - Network connectivity issues\n\n**Solutions:**\n- Verify token has correct permissions\n- Check repository URL format\n- Create file manually for first use\n- Test network connection\n\n#### \"HTTP Error 401\"\n\n\u003e [!CAUTION]\n\u003e **Possible causes:**\n\u003e - Invalid or expired token\n\u003e - Missing \"Bearer \" prefix in token\n\n**Solutions:**\n- Generate a new GitHub token\n- Ensure token includes \"Bearer \" prefix\n\n#### \"HTTP Error 422\"\n\n\u003e [!CAUTION]\n\u003e **Possible causes:**\n\u003e - Invalid JSON format\n\u003e - Base64 encoding issues\n\n**Solutions:**\n- Verify JSON structure\n- Check Base64 encoding implementation\n\n### Debugging Techniques\n\nEnable debug output by defining `DEBUG_GITHUBIOT` before including the library:\n\n```cpp\n#define DEBUG_GITHUBIOT\n#include \u003cgithubiot.h\u003e\n```\n\n---\n\n## Advanced Usage\n\n### Updating Existing JSON Files\n\nTo update an existing JSON file while preserving its structure:\n\n```cpp\n// Get current file\nString sha = iot_module.get_current_sha();\n\n// Download and parse existing content\n// (implementation not shown - would require custom HTTP GET handler)\n\n// Update specific fields\nexistingDoc[\"last_updated\"] = time(NULL);\nexistingDoc[\"readings\"][0][\"value\"] = newValue;\n\n// Upload updated content\niot_module.upload_to_github(existingDoc, sha);\n```\n\n### Custom Commit Messages\n\nThe current implementation uses a fixed commit message (\"Update data\"). For custom messages, the library would need to be extended.\n\n### Error Handling Strategy\n\nImplement a robust error handling strategy:\n\n```cpp\nString sha = iot_module.get_current_sha();\nif (sha == \"\") {\n    // Handle error: could not get SHA\n    retryWithBackoff();\n    return;\n}\n\n// Prepare data\nDynamicJsonDocument doc(1024);\ndoc[\"sensor\"] = \"temperature\";\ndoc[\"value\"] = readSensor();\n\n// Try to upload with retry\nbool success = false;\nint retries = 0;\nwhile (!success \u0026\u0026 retries \u003c MAX_RETRIES) {\n    // Upload to GitHub\n    int result = iot_module.upload_to_github(doc, sha);\n    if (result == 200) {\n        success = true;\n    } else {\n        retries++;\n        delay(1000 * retries); // Exponential backoff\n    }\n}\n```\n\n---\n\n## License\n\nThis library is released under the `MIT` License.\n\n## Author\n1. GALIH RIDHO UTOMO\n2. Fionita Fahra Azzahra\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgalihru%2Fgithubiot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgalihru%2Fgithubiot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgalihru%2Fgithubiot/lists"}