{"id":19099521,"url":"https://github.com/dentrax/mmm-arduport","last_synced_at":"2025-04-30T16:21:57.840Z","repository":{"id":44699372,"uuid":"165304097","full_name":"Dentrax/MMM-ArduPort","owner":"Dentrax","description":"This is a module for the MagicMirror² smart mirror project. This module provides Arduino serial communication support with Raspberry PI.","archived":false,"fork":false,"pushed_at":"2024-04-20T23:17:11.000Z","size":100,"stargazers_count":18,"open_issues_count":7,"forks_count":5,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-19T05:15:45.594Z","etag":null,"topics":["arduino","arduino-platform","communication","magicmirror","magicmirror2","module","plugin","python","python-library","python-script","raspberry-pi","serial","serialport"],"latest_commit_sha":null,"homepage":"https://magicmirror.builders/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Dentrax.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2019-01-11T20:16:17.000Z","updated_at":"2024-12-30T16:05:06.000Z","dependencies_parsed_at":"2024-11-09T03:51:16.434Z","dependency_job_id":"6c56e2da-ce34-4c8c-bea3-9f5ab8bc6a41","html_url":"https://github.com/Dentrax/MMM-ArduPort","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dentrax%2FMMM-ArduPort","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dentrax%2FMMM-ArduPort/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dentrax%2FMMM-ArduPort/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dentrax%2FMMM-ArduPort/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Dentrax","download_url":"https://codeload.github.com/Dentrax/MMM-ArduPort/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251739950,"owners_count":21635950,"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":["arduino","arduino-platform","communication","magicmirror","magicmirror2","module","plugin","python","python-library","python-script","raspberry-pi","serial","serialport"],"created_at":"2024-11-09T03:51:08.255Z","updated_at":"2025-04-30T16:21:57.818Z","avatar_url":"https://github.com/Dentrax.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# MMM-ArduPort\nThis is a module for the [MagicMirror²](https://github.com/MichMich/MagicMirror/tree/develop) smart mirror project.\n\nThis module provides Arduino serial communication support with Raspberry PI.\n\nI created this module for my project real-time [ArduRMMMQ](https://github.com/Dentrax/ArduRMMMQ) project.\n\n| Status  | Version | Date       | Maintained? | Minimum MagicMirror² Version |\n|:------- |:------- |:---------- |:----------- |:---------------------------- |\n| Working | `1.0.0` | 2019-01-11 | Yes         |`2.0.0`                       |\n\n## Screenshots\n\n![MMM-ArduPort Running](screenshots/mmmarduport_running.png?raw=true \"Screenshot\")\n\n![MMM-ArduPort Running](screenshots/mmmarduport_waiting-module.png?raw=true \"Screenshot\")\n\n![MMM-ArduPort Running](screenshots/mmmarduport_waiting-arduino.png?raw=true \"Screenshot\")\n\n![MMM-ArduPort Running](screenshots/mmmarduport_starting.png?raw=true \"Screenshot\")\n\n## Dependencies\n\n- [python-shell](https://www.npmjs.com/package/python-shell)\n\n- [pyserial](https://pypi.org/project/pyserial)\n\n## Installation\n\nTo install the module, use your terminal to:\n\n1. Navigate to your MagicMirror's `modules` folder. If you are using the default installation directory, use the command: \n```\ncd ~/MagicMirror/modules\n```\n\n2. Clone the module to your computer by executing the following command:\n```\ngit clone https://github.com/Dentrax/MMM-ArduPort.git\n```\n\n3. Install the `python-shell` library by executing the following command:\n```\nnpm install\n```\n\n* Configure the module in your `config.js` file.\n\n## Using the module\n\n### MagicMirror² Configuration\n\nTo use this module, add the following configuration block to the modules array in the `config/config.js` file:\n```js\nvar config = {\n    modules: [\n        ...\n        {\n            module: \"MMM-ArduPort\",\n            position: \"bottom_right\",\n            header: \"MMM-ArduPort\",\n            config: {\n                // See below for more Configuration Options\n            }\n        },\n        ...\n    ]\n}\n```\n### Configuration Options\n\n\u003ctable\u003e\n  \u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth\u003eOption\u003c/th\u003e\n      \u003cth\u003eDescription\u003c/th\u003e\n      \u003cth\u003eValue\u003c/th\u003e\n      \u003cth\u003eDefault\u003c/th\u003e\n    \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ccode\u003eportname\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003cstrong\u003eREQUIRED\u003c/strong\u003e\u003cbr\u003eThe port name to which the Arduino will be connected\u003cbr\u003e\u003cbr\u003e\u003cstrong\u003eExample:\u003c/strong\u003e \u003ccode\u003e\"/dev/ttyUSB0\"\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003estring\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003eNULL\u003c/code\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ccode\u003edisplayIcons\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003eShows specific icons of the sensors\u003cbr\u003e\u003cbr\u003e\u003c/td\u003e\n      \u003ctd\u003eboolean\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003eNULL\u003c/code\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ccode\u003eshowDescription\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003eShows the descriptions of the sensors\u003cbr\u003e\u003c/td\u003e\n      \u003ctd\u003eboolean\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003efalse\u003c/code\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ccode\u003ehideLoading\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003eHide loding animation\u003cbr\u003e\u003c/td\u003e\n      \u003ctd\u003eboolean\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003efalse\u003c/code\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ccode\u003ehideWaiting\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003eHide waiting animation if the sensor did not send any data yet\u003cbr\u003e\u003c/td\u003e\n      \u003ctd\u003eboolean\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003efalse\u003c/code\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ccode\u003euseColors\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003eUse colorful texts\u003cbr\u003e\u003c/td\u003e\n      \u003ctd\u003eboolean\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003etrue\u003c/code\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ccode\u003esensors\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003cstrong\u003eREQUIRED\u003c/strong\u003e\u003cbr\u003eSensor array to be used in the module\u003cbr\u003e\u003cbr\u003e\u003c/td\u003e\n      \u003ctd\u003earray\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003eNULL\u003c/code\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\nEach object in the `sensors` array can have the following parameters:\n\n\u003ctable\u003e\n  \u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth\u003eOption\u003c/th\u003e\n      \u003cth\u003eDescription\u003c/th\u003e\n      \u003cth\u003eValues\u003c/th\u003e\n      \u003cth\u003eDefault\u003c/th\u003e\n    \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ccode\u003ename\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003cstrong\u003eREQUIRED\u003c/strong\u003e\u003cbr\u003eThe name of the sensor (case-sensitive, no space)\u003cbr\u003e\u003cbr\u003e\u003cstrong\u003eExample:\u003c/strong\u003e \u003ccode\u003e\"HCSR04\"\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003estring\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003eNULL\u003c/code\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ccode\u003edescription\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003eIf \u003ccode\u003eshowDescription\u003c/code\u003e = \u003ccode\u003etrue\u003c/code\u003e description shown under the sensor\u003cbr\u003e\u003cbr\u003e\u003cstrong\u003eExample:\u003c/strong\u003e \u003ccode\u003e\"My awesome description\"\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003estring\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003eNULL\u003c/code\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ccode\u003emaxValue\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003eMAXIMUM value that the sensor can produce\u003cbr\u003e\u003cbr\u003e\u003c/td\u003e\n      \u003ctd\u003einteger\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003eNULL\u003c/code\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ccode\u003emaxFormat\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003eTo format the string shown on the screen\u003cbr\u003e\u003cbr\u003e\u003cstrong\u003eExample:\u003c/strong\u003e \u003ccode\u003e({0}) MAX\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003estring\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003eNULL\u003c/code\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ccode\u003ehighestValue\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003eHIGHEST value that the sensor can produce\u003cbr\u003e\u003cbr\u003e\u003c/td\u003e\n      \u003ctd\u003einteger\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003eNULL\u003c/code\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ccode\u003ehighestFormat\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003eTo format the string shown on the screen\u003cbr\u003e\u003cbr\u003e\u003cstrong\u003eExample:\u003c/strong\u003e \u003ccode\u003e({0}) HIGHEST\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003estring\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003eNULL\u003c/code\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ccode\u003ehighValue\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003eHIGH value that the sensor can produce\u003cbr\u003e\u003cbr\u003e\u003c/td\u003e\n      \u003ctd\u003einteger\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003eNULL\u003c/code\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ccode\u003ehighFormat\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003eTo format the string shown on the screen\u003cbr\u003e\u003cbr\u003e\u003cstrong\u003eExample:\u003c/strong\u003e \u003ccode\u003e({0}) HIGH\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003estring\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003eNULL\u003c/code\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ccode\u003elowValue\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003eLOW value that the sensor can produce\u003cbr\u003e\u003cbr\u003e\u003c/td\u003e\n      \u003ctd\u003einteger\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003eNULL\u003c/code\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ccode\u003elowFormat\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003eTo format the string shown on the screen\u003cbr\u003e\u003cbr\u003e\u003cstrong\u003eExample:\u003c/strong\u003e \u003ccode\u003e({0}) LOW\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003estring\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003eNULL\u003c/code\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ccode\u003elowestValue\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003eLOWEST value that the sensor can produce\u003cbr\u003e\u003cbr\u003e\u003c/td\u003e\n      \u003ctd\u003einteger\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003eNULL\u003c/code\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ccode\u003elowestFormat\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003eTo format the string shown on the screen\u003cbr\u003e\u003cbr\u003e\u003cstrong\u003eExample:\u003c/strong\u003e \u003ccode\u003e({0}) LOWEST\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003estring\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003eNULL\u003c/code\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ccode\u003eminValue\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003eMINIMUM value that the sensor can produce\u003cbr\u003e\u003cbr\u003e\u003c/td\u003e\n      \u003ctd\u003einteger\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003eNULL\u003c/code\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ccode\u003eminFormat\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003eTo format the string shown on the screen\u003cbr\u003e\u003cbr\u003e\u003cstrong\u003eExample:\u003c/strong\u003e \u003ccode\u003e({0}) MIN\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003estring\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003eNULL\u003c/code\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\nHere is an example of an entry in `config.js` with full-feature.\n\n```\n...\n        {\n\t          module: 'MMM-ArduPort',\n\t          position: 'bottom_left',\n              header: 'Arduino Sensors',\n              config: {\n                portname: \"/dev/ttyUSB0\",\n                updateInterval: 1,\n                animationSpeed: 1000,\n                displayIcons: true,\n                showDescription: true,\n                hideLoading: false,\n                hideWaiting: false,\n                useColors: true,\n                sensors: [\n                    {\n                        name: \"MQ2\",\n                        description: \"LPG, Propane, Hydrogen\",\n                        maxValue: 50,\n                        maxFormat: \"({0} ppm) MAXIMUM\",\n                        highestValue: 30,\n                        highestFormat: \"({0} ppm) CRITICAL\",\n                        highValue: 15,\n                        highFormat: \"({0} ppm) EMERGENCY\",\n                        lowValue: 10,\n                        lowFormat: \"({0} ppm) LOW\",\n                        lowestValue: 5,\n                        lowestFormat: \"({0} ppm) VERY LOW\",\n                        minValue: 0,\n                        minFormat: \"({0} ppm) OK\"\n                    },\n                    {\n                        name: \"LM35\",\n                        description: \"Temperature\",\n                        maxValue: 50,\n                        maxFormat: \"({0}°C) VERY HIGH\",\n                        highestValue: 30,\n                        highestFormat: \"({0}°C) HIGH\",\n                        highValue: 15,\n                        highFormat: \"({0}°C) NORMAL\",\n                        lowValue: 10,\n                        lowFormat: \"({0}°C) LOW\",\n                        lowestValue: 5,\n                        lowestFormat: \"({0}°C) VERY LOW\",\n                        minValue: 0,\n                        minFormat: \"({0}°C) OK\"\n                    },\n                    {\n                        name: \"HCSR04\",\n                        description: \"Distance\",\n                        maxValue: 50,\n                        maxFormat: \"({0} cm) TOO FAR\",\n                        highestValue: 30,\n                        highestFormat: \"({0} cm) FAR\",\n                        highValue: 15,\n                        highFormat: \"({0} cm) NORMAL\",\n                        lowValue: 10,\n                        lowFormat: \"({0} cm) CLOSE\",\n                        lowestValue: 5,\n                        lowestFormat: \"({0} cm) TOO CLOSE\",\n                        minValue: 0,\n                        minFormat: \"({0} cm) OK\"\n                    },\n                ]\n            }\n        },\n...\n```\n\n## Using the Arduino\n\nTo communicate between `Arduino` and `MMM-ArduPort`, serial communication must be in this format:\n\n```\nSerial.println(\"[COMMAND:NAME:DATA]\")\n```\n\n### Starting the module\n\n**IMPORTANT:** Do not any send sensor data in the `setup()` function.\n\nIn order to start the module, the Arduino's `setup()` function must be completed.\n\n- To send `starting` signal: `[status:setup:starting]`\n\n- To send `started` signal: `[status:setup:started]`\n\n- To send `failed` signal: `[status:setup:failed]**\n\n**Example:**\n\n```\nSerial.println(\"[status:setup:starting]\");\nSerial.println(\"[status:setup:failed]\");\nSerial.println(\"[status:setup:started]\");\n```\n\n### Sending data to module\n\n**IMPORTANT:** The signal command you send must be registered as name in the `sensors*** array.\n\n**Example**\n```\n                sensors: [\n                    {\n                        name: \"MQ2\",\n                    },\n                    {\n                        name: \"LM35\",\n                    },\n                    {\n                        name: \"HCSR04\",\n                    },\n```\n\nTo transmit a sensor data to the module: `[sensor:SENSOR_NAME:SENSOR_VALUE]**\n\n**Example:**\n\n```\nSerial.println(\"[sensor:MQ2:19]\");\nSerial.println(\"[sensor:LM35:11]\");\nSerial.println(\"[sensor:HCSR04:64]\");\n```\n\n### Full Arduino Example\n\n```\nvolatile int32_t m_counter = 0;\nbool WasStarted = false;\n\nstatic const char *pcMQ2Prefix = \"[sensor:MQ2:\";\nstatic const char *pcLM35Prefix = \"[sensor:LM35:\";\nstatic const char *pcHCSR04Prefix = \"[sensor:HCSR04:\";\nstatic const char *pcPostfix = \"]\";\n\nvoid setup() {\n  Serial.begin(9600);\n  while(!Serial);\n  \n  Serial.println(\"[status:setup:starting]\");\n  \n  int test = 1;\n  m_counter = test;\n\n  if(test \u003e 1) {\n    WasStarted = false;\n    Serial.println(\"[status:setup:failed]\");\n    return;\n  }\n  \n  delay(3000);\n  WasStarted = true;\n  Serial.println(\"[status:setup:started]\");\n  delay(100);\n}\n\nvoid loop() {\n  Serial.print(pcMQ2Prefix);\n  Serial.print(m_counter);\n  Serial.println(pcPostfix);\n\n  if(m_counter % 3 == 0) {\n    delay(1000);\n    Serial.print(pcLM35Prefix);\n    Serial.print(m_counter + 11);\n    Serial.println(pcPostfix);\n    delay(2000);\n    Serial.print(pcHCSR04Prefix);\n    Serial.print(m_counter + 33);\n    Serial.println(pcPostfix);\n  }\n\n  if(m_counter \u003e= 60) m_counter = 0;\n  m_counter++;\n\n  delay(1000);\n}\n```\n\n## Known Issues\n\n**Do not use `Serial.print()` instead of `Serial.println()` (Not supported yet)**\n\n- ISSUE: When the Arduino's reset button is pressed, sometimes the connection is terminated.\n- FIX:\n```\n1. Disconnect the Arduino from the PC\n2. Close the MagicMirror\n3. Re-open the MagicMirror again\n4. Connect Arduino to PC again\n```\n\n## Special Thanks\n\n- [Michael Teeuw](https://github.com/MichMich) for creating the awesome [MagicMirror²](https://github.com/MichMich/MagicMirror/tree/develop) project that made this module possible.\n- [Jeff Clarke](https://github.com/jclarke0000/MMM-MyCommute) for creating awesome module design (that i use in this project) and inspires me to do this module.\n\n## License\n\n### The MIT License (MIT)\n\nCopyright © 2018 Furkan 'Dentrax' Türkal\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the “Software”), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\n**The software is provided “as is”, without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the software.**\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdentrax%2Fmmm-arduport","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdentrax%2Fmmm-arduport","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdentrax%2Fmmm-arduport/lists"}