{"id":17970277,"url":"https://github.com/cortinico/myonnaise","last_synced_at":"2025-03-25T11:31:19.762Z","repository":{"id":43399063,"uuid":"39206404","full_name":"cortinico/myonnaise","owner":"cortinico","description":"🍯 A RxJava library to access Raw EMG data from your Myo 📈 (plus an Android companion App 📱)","archived":false,"fork":false,"pushed_at":"2025-03-24T20:09:31.000Z","size":1584,"stargazers_count":30,"open_issues_count":6,"forks_count":16,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-03-24T21:23:26.300Z","etag":null,"topics":["bluetooth","emg-data","emg-signal","hacktoberfest","myo","myo-armband","myo-device","myo-devices","myo-sdk","raw-data","rxandroid","rxandroid2","rxandroid2-sample","rxjava","rxjava-android","rxjava2"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","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/cortinico.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":"2015-07-16T15:52:17.000Z","updated_at":"2025-02-26T22:04:09.000Z","dependencies_parsed_at":"2024-10-16T18:33:13.403Z","dependency_job_id":"174328ff-8004-4a12-b7b8-0b37417e2946","html_url":"https://github.com/cortinico/myonnaise","commit_stats":{"total_commits":120,"total_committers":2,"mean_commits":60.0,"dds":"0.15000000000000002","last_synced_commit":"09ed4f14e3ff8695097eecfa2514abd61af6d4a2"},"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cortinico%2Fmyonnaise","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cortinico%2Fmyonnaise/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cortinico%2Fmyonnaise/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cortinico%2Fmyonnaise/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cortinico","download_url":"https://codeload.github.com/cortinico/myonnaise/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245453881,"owners_count":20617934,"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":["bluetooth","emg-data","emg-signal","hacktoberfest","myo","myo-armband","myo-device","myo-devices","myo-sdk","raw-data","rxandroid","rxandroid2","rxandroid2-sample","rxjava","rxjava-android","rxjava2"],"created_at":"2024-10-29T15:02:44.368Z","updated_at":"2025-03-25T11:31:19.707Z","avatar_url":"https://github.com/cortinico.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Myonnaise 🍯\n[![Pre Merge Checks](https://github.com/cortinico/myonnaise/actions/workflows/pre-merge.yaml/badge.svg)](https://github.com/cortinico/myonnaise/actions/workflows/pre-merge.yaml) [![codecov](https://codecov.io/gh/cortinico/myonnaise/branch/master/graph/badge.svg)](https://codecov.io/gh/cortinico/myonnaise) [ ![Download](https://api.bintray.com/packages/cortinico/maven/myonnaise/images/download.svg) ](https://bintray.com/cortinico/maven/myonnaise/_latestVersion) ![License](https://img.shields.io/badge/license-MIT%20License-brightgreen.svg) [![Twitter](https://img.shields.io/badge/Twitter-@cortinico-blue.svg?style=flat)](http://twitter.com/cortinico)\n\n\u003cp align=\"center\"\u003e\n    \u003cimg width=\"30%\" src=\"https://raw.githubusercontent.com/cortinico/myonnaise/master/icon_hires.png\" alt=\"projectlogo\"\u003e\n\u003c/p\u003e\n\nAn Android library to interact with your Thalmic **Myo**, written in [**Kotlin**](https://github.com/JetBrains/kotlin) and using [**RxJava2**](https://github.com/ReactiveX/RxJava). \n\nThis repo contains also a **sample app** that showcases the usage of the library: Myo EMG Visualizer. With this app you can stream EMG Raw data from your device and **save it as a CSV**. The app is also available on the play store:\n\n\u003ca href='https://play.google.com/store/apps/details?id=it.ncorti.emgvisualizer\u0026pcampaignid=MKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1'\u003e\u003cimg alt='Get it on Google Play' width=\"20%\" src='https://play.google.com/intl/en_gb/badges/images/generic/en_badge_web_generic.png'/\u003e\u003c/a\u003e\n\n**DISCLAIMER: If you don't know what a Myo is, please go here: [support.getmyo.com](https://support.getmyo.com/). Please note that you need a Myo in order to use this library/app.**\n\n- [Myonnaise 🍯](#myonnaise-)\n  - [Getting Started 👣](#getting-started-)\n  - [Example 🚸](#example-)\n    - [Searching for a Myo](#searching-for-a-myo)\n    - [Connecting to a Myo](#connecting-to-a-myo)\n    - [Sending a Command](#sending-a-command)\n    - [Starting the Streaming](#starting-the-streaming)\n    - [Streaming Frequency](#streaming-frequency)\n    - [Keep Alive](#keep-alive)\n  - [Features 🎨](#features-)\n  - [Test App 📲](#test-app-)\n    - [Videos](#videos)\n  - [Building/Testing ⚙️](#buildingtesting-️)\n    - [GitHub Actions](#github-actions)\n    - [Codecov ](#codecov-)\n    - [Building locally](#building-locally)\n    - [Testing](#testing)\n  - [Contributing 🤝](#contributing-)\n  - [License 📄](#license-)\n\n## Getting Started 👣\n\n**Myonnaise** is distributed through [JCenter](https://bintray.com/bintray/jcenter?filterByPkgName=myonnaise). To use it you need to add the following **Gradle dependency** to your **android app gradle file** (NOT the root file).\n\n```groovy\ndependencies {\n   implementation(\"com.ncorti:myonnaise:1.0.0\")\n}\n```\n\n## Example 🚸\n\nAfter setting up the Gradle dependency, you will be able to access two main classes: `Myonnaise` and `Myo`. \n\n* [`Myonnaise`](https://github.com/cortinico/myonnaise/blob/master/myonnaise/src/main/java/com/ncorti/myonnaise/Myonnaise.kt) is the entry point where you can **trigger a bluetooth scan** to search for nearby devices. A scan will return you one or mode `BluetoothDevice` (from the [android framework](https://developer.android.com/reference/android/bluetooth/BluetoothDevice)). If you don't know your Myo's address a priori, you need to show those devices to the user and allow him to pick one.\n\n* [`Myo`](https://github.com/cortinico/myonnaise/blob/master/myonnaise/src/main/java/com/ncorti/myonnaise/Myo.kt) is the class that will allow you to connect to your device, send commands and start the streaming. You need a `BluetoothDevice` in order to create a `Myo`.\n\n### Searching for a Myo\n\nFirst, you need to **find a Myo** with a bluetooth scan.\n\n** ⚠️ Please note that you need to request the user the ACCESS_FINE_LOCATION permission. If not, the scan will be empty ⚠️ **\n\nTo start a bluetooth scan, you can use the `startScan()` method:\n\n```kotlin\nMyonnaise(context).startScan()\n            .subscribeOn(Schedulers.io())\n            .observeOn(AndroidSchedulers.mainThread())\n            .subscribe({\n                // Do something with the found device\n                println(it.address)\n            })\n```\n\nThis method will return a `Flowable` that will publish all the `BluetoothDevice` that are discovered nearby. Please note that the scan will stop only when you **cancel** the Flowable.\n\nAlternatively, you can also provide a **timeout** and the scan will stop after the timeout:\n\n```kotlin\nMyonnaise(context).startScan(5, TimeUnit.MINUTES)\n            .subscribeOn(Schedulers.io())\n            .observeOn(AndroidSchedulers.mainThread())\n            .subscribe({\n                // Do something with the found device\n                println(it.address)\n            })\n```\n\nOnce you found a `BluetoothDevice` that is a Myo, you can get a `Myo` instance from it.\n\n```kotlin\nval myMyo = Myonnaise.getMyo(foundDevice)\n```\n\n### Connecting to a Myo\n\nConnecting or disconnecting to a Myo is really easy:\n\n```kotlin\n// To Connect\nmyMyo.connect(getContext())\n\n// To Disconnect\nmyMyo.disconnect()\n```\nConnecting and disconnecting are **not syncronous** operations. You have to wait that the device is successfully connected before start sending commands.\nYou can **get notified** of status updates using the RxJava `statusObservable`.\n\n```kotlin\nmyMyo.statusObservable()\n        .subscribeOn(Schedulers.io())\n        .observeOn(AndroidSchedulers.mainThread())\n        .subscribe {\n            when (it) {\n                MyoStatus.CONNECTED -\u003e { /* ... */ }\n                MyoStatus.CONNECTING -\u003e { /* ... */ }\n                MyoStatus.READY -\u003e { /* ... */ }\n                else -\u003e { /* ... */ } // DISCONNECTED\n            }\n        }\n```\n\nIn order to send command to your `Myo`, your `Myo` should be in the **READY** state. If the `Myo` is not ready, commands will be ignored.\n\n### Sending a Command\n\nTo send a command you can use the `sendCommand()` method. For example, you can let your device vibrate with:\n\n```kotlin\nmyMyo.sendCommand(CommandList.vibration1())\n```\n\nCommands will be processed by the library and sent to the device (the library has a queue to process all the commands).\n\nList of all available commands is in the [`CommandList.kt`](https://github.com/cortinico/myonnaise/blob/master/myonnaise/src/main/java/com/ncorti/myonnaise/Myo.kt) file.\n\n### Starting the Streaming\n\nYou can start/stop the streaming using again the `sendCommand` method:\n\n```kotlin\n// Start Streaming\nmyMyo.sendCommand(CommandList.emgUnfilteredOnly())\n\n// Stop Streaming\nmyMyo.sendCommand(CommandList.stopStreaming())\n```\n\nYou will start receiving the streaming of data as a `Flowable\u003cFloatArray\u003e` through the `dataFlowable()` method. To collect the data, just subscribe to the flowable:\n\n```kotlin\nmyMyo.dataFlowable()\n        .subscribeOn(Schedulers.io())\n        .observeOn(AndroidSchedulers.mainThread())\n        .subscribe {\n            println(it) // it is an array of 8 floats.\n        }\n```\n\n### Streaming Frequency\n\nYou can change the **streaming frequency** to receive less data. By default data is streamed at **200Hz** (the max supported by the device). You can subsample the data if you set the **frequency** property:\n\n```kotlin\nmyMyo.frequency = 50 // Streaming at 50Hz\n```\n\nAllowed values are from 0 (reset to default) to 200.\n\n### Keep Alive\n\nThe Myo will go to _sleep_ if he receives no intereaction within some seconds. For this reason we are sending a `CommandList.unSleep()` every 10 seconds, in order to keep the connection always on.\n\nIf you don't want this behavior, just turn off the keep alive:\n\n```kotlin\nmyMyo.keepAlive = false\n```\n\n## Features 🎨\n\n* **100% Kotlin** (but you don't need Kotlin to use it)!\n* Uses **RxJava**. You don't need to poll for status update, the library will call you.\n* Unleash the full Myo power, Raw Data Streaming at **200Hz**! 💪\n* Small footprint: The AAR is just **36Kb**\n* **API \u003e= 21** compatible (due to BluetoothLE limitations).\n* Easy to integrate (just a gradle `implementation` line).\n\n## Test App 📲\n\nYou can find the test app (Myo Emg Visualizer) inside the `app` module. \n\n\u003cp align=\"center\"\u003e\n    \u003cimg alt=\"test-app\" src=\"https://i.imgur.com/lcAbyJD.png\" width=\"30%\"\u003e\n\u003c/p\u003e\n\nThis app allows you to:\n\n* Scan for a Myo\n* Connect to a Myo, control the frequency and send vibration.\n* See a graph of the **EMG data**.\n* Export the EMG data as a **CSV file**\n\nSome technical features are:\n\n* The app is 100% Kotlin.\n* Architecture pattern used: MVP.\n* Dagger Android to inject the views.\n* Use AndroidX.\n* Use the Material Design Components library.\n\n### Videos\n\n**Searching for a Myo**\n\n\u003cimg alt=\"searching-for-a-myo\" src=\"https://i.imgur.com/ShZP4w5.gif\" width=\"30%\"/\u003e\n\n**Starting the Streaming**\n\n\u003cimg alt=\"start-streaming\" src=\"https://i.imgur.com/iqvkQfr.gif\" width=\"30%\"/\u003e\n\n**Exporting to CSV**\n\n\u003cimg alt=\"exporting-the-csv\" src=\"https://i.imgur.com/4UXIas9.gif\" width=\"30%\"/\u003e\n\n\n## Building/Testing ⚙️\n\n### GitHub Actions \n\n[![Pre Merge Checks](https://github.com/cortinico/myonnaise/actions/workflows/pre-merge.yaml/badge.svg)](https://github.com/cortinico/myonnaise/actions/workflows/pre-merge.yaml) \n\nThis projects is built with GitHub Actions. The CI environment takes care of building the library .AAR, the example app and to run the **JUnit** tests. Test and lint reports are exposes in the **artifacts** section at the end of every build.\n\n### Codecov \n\n[![codecov](https://codecov.io/gh/cortinico/myonnaise/branch/master/graph/badge.svg)](https://codecov.io/gh/cortinico/myonnaise)\n\nCircle CI is responsible of uploading Jacoco reports to [Codecov](https://codecov.io/gh/cortinico/myonnaise). When opening a Pull Request, Codecov will post a report of the diff of the test coverage.\n\nPlease **don't ignore it**! PR with new features and **without** are likely to be discarded 😕\n\n### Building locally\n\nThen just clone the repo locally and build the .AAR with the following command:\n\n```bash\ngit clone git@github.com:cortinico/myonnaise.git\ncd myonnaise/\n./gradlew build\n```\nThe assembled .AAR (library) will be inside the **myonnaise/build/outputs/aar** folder.\nThe assembled .APK (application) will be inside the **app/build/outputs/apk/debug** folder.\n\n### Testing\n\nOnce you're able to build successfully, you can run JUnit tests locally with the following command.\n\n```bash\n./gradlew test \n```\nPlease note that there are tests inside the `myonnaise` and the `app` module. The `app` module contains test for the presenters. The `myonnaise` module contains tests for the library.\n\nMake sure your tests are all green ✅ locally before submitting PRs.\n\n## Contributing 🤝\n\n**Looking for contributors! Don't be shy.** 😁 Feel free to open issues/pull requests to help me improve this project.\n\n* When reporting a new Issue, make sure to attach **Screenshots** of the problem you are reporting. \n* Debugging \n* When submitting a new PR, make sure tests are all green. Write new tests if necessary (would be great if the code coverage doesn't decrease).\n\n## License 📄\n\nThis project is licensed under the MIT License - see the [License](LICENSE) file for details\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcortinico%2Fmyonnaise","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcortinico%2Fmyonnaise","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcortinico%2Fmyonnaise/lists"}