├── .eslintrc
├── .gitignore
├── .npmignore
├── .travis.yml
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── ROADMAP.md
├── examples
├── browser
│ ├── index.html
│ └── index.js
└── node
│ └── index.js
├── images
└── node_icon2.png
├── package.json
├── src
├── constants.js
├── debug.js
├── index.js
└── utilities.js
├── test
├── bluebirdChecks.js
├── openBCIConstants-test.js
├── openBCIUtilities-test.js
└── timingEventsAsPromises.js
└── webpack.config.js
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["semistandard"],
3 | "plugins": [
4 | "chai-friendly"
5 | ],
6 | "rules": {
7 | "no-unused-expressions": 0,
8 | "chai-friendly/no-unused-expressions": 2
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 | ### Node template
3 | # Logs
4 | logs
5 | *.log
6 | npm-debug.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
24 | .grunt
25 |
26 | # node-waf configuration
27 | .lock-wscript
28 |
29 | # Compiled binary addons (http://nodejs.org/api/addons.html)
30 | build/Release
31 |
32 | # Dependency directories
33 | node_modules
34 | jspm_packages
35 |
36 | # Optional npm cache directory
37 | .npm
38 |
39 | # Optional eslint cache
40 | .eslintcache
41 |
42 | # Optional REPL history
43 | .node_repl_history
44 |
45 | # Output of 'npm pack'
46 | *.tgz
47 |
48 | # Yarn Integrity file
49 | .yarn-integrity
50 |
51 | # Webstorm
52 | .idea
53 | .idea/*.xml
54 | .DS_Store
55 |
56 | dist
57 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | test/
2 | test_mocks/
3 |
4 | # MIRRORED FROM .gitignore PLEASE MAINTAIN
5 | logs
6 | *.log
7 | pids
8 | *.pid
9 | *.seed
10 | lib-cov
11 | coverage
12 | .grunt
13 | .lock-wscript
14 | build/Release
15 | node_modules
16 | .idea
17 | .DS_Store
18 | public
19 | myOutput.txt
20 | *.tgz
21 | openBCISerialFormat
22 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "4.8.4"
4 | - "6"
5 | - "7"
6 | - "8"
7 | - "9"
8 | install:
9 | - npm install --all
10 | script:
11 | - npm run test
12 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # v1.0.0
2 |
3 | ### Breaking Changes
4 |
5 | - Name of package is now @openbci/cyton
6 |
7 | # v0.3.6
8 |
9 | ### Bug Fixes
10 |
11 | - Fix bug where parseGanglion could result in a concat of non-buffer types
12 |
13 | # v0.3.5
14 |
15 | ### Bug Fixes
16 |
17 | - Fix bug where `getFirmware` failed for patch or minor versions over 9 (aka double digits)
18 |
19 | # v0.3.4
20 |
21 | ### Bug Fixes
22 |
23 | - Protect and ensure buffer returned for raw data packets
24 |
25 | # v0.3.3
26 |
27 | ### Enhancements
28 |
29 | - Add raw of version to `getFirmware`
30 | - Bump mathjs to 4.0.0 to resolve insecurity
31 |
32 | # v0.3.1
33 |
34 | ### Enhancements
35 |
36 | - Removed `lodash` from dependencies to reduce bundle size (thanks @alexcastillo!!)
37 |
38 | # v0.3.0
39 |
40 | You can now use this module in the browser!! Huge should out to @alexcastillo for help with making with refactoring the project!
41 |
42 | ### Breaking Changes
43 |
44 | - Removed simulator file back into cyton repo
45 | - Removed `safe-buffer` in place of `buffer`
46 | - Removed support for node version 5 and below
47 | - `Utilities` changed to to `utilities`
48 | - `Constants` is now `constants`
49 | - Inidividual functions can now be importated from the utilities module.
50 |
51 | # v0.2.7
52 |
53 | ### Bug Fixes
54 |
55 | - No `stopByte` property for daisy samples. Added tests.
56 |
57 | # v0.2.6
58 |
59 | ### Bug Fixes
60 |
61 | - Accel data with counts did not work for cyton with daisy over wifi.
62 |
63 | # v0.2.5
64 |
65 | ### Bug Fixes
66 |
67 | - Had incorrect ganglion accel multiplication factor of 32mg per count but was really 16mg per count
68 | - `newSample` and `newSampleNoScale` in utility file did not have `valid` is `true` property.
69 |
70 | # v0.2.4
71 |
72 | ### New Features
73 |
74 | - Add new constants for emitter
75 |
76 | ### Bug Fixes
77 |
78 | - Fix bug where ganglion sample channel data when scale was false produced array of 8 values instead of 4
79 |
80 | # v0.2.3
81 |
82 | ### New Features
83 |
84 | - Add function for parsing an impedance object `.parsePacketImpedance()`
85 |
86 | # v0.2.2
87 |
88 | ### Bug Fixes
89 |
90 | - Fix wrap around bug in extractRawBLEDataPackets
91 |
92 | # v0.2.1
93 |
94 | ### Bug Fixes
95 |
96 | - Accel data with counts did not work for cyton with daisy. Also fixed up some test errors with the effected functions.
97 |
98 | ### New Features
99 |
100 | - Add features for `openbci-ganglion`
101 |
102 | # v0.2.0
103 |
104 | ### New Feature
105 |
106 | - With scale option false, `.parsePacketStandardAccel()` `.parsePacketTimeSyncedAccel()` will now return array called will now return `accelDataCounts` property with un-scaled data.
107 |
108 | # v0.1.5
109 |
110 | ### Bug Fixes
111 |
112 | - Was missing errors in constants used by ganglion and other ble projects.
113 | - Fixed getChannelData functions to support 2 channel cytons
114 |
115 | # v0.1.4
116 |
117 | ### Bug Fixes
118 |
119 | - E-patch on new function added 0.1.3
120 |
121 | # v0.1.3
122 |
123 | ### New Features
124 |
125 | - A bunch of functions to support synchronization of channel settings with cyton. Will be used by both the Wifi and the Cyton node modules.
126 |
127 | # v0.1.2
128 |
129 | ### Bug Fixes
130 |
131 | - Send counts did not work for daisy.
132 | - Sample output was inconsistent
133 | - Fixed `timeStamp` to `timestamp` this was pr #147 (thanks @alexdevmotion)
134 |
135 | # v0.1.1
136 |
137 | ### Bug Fixes
138 |
139 | - Send counts did not work for daisy.
140 |
141 | # v0.1.0
142 |
143 | ### New Functions
144 |
145 | - Add function `getFirmware(dataBuffer)` to utilities
146 |
147 | ### Breaking Changes
148 |
149 | - Removed function called `findV2Firmware()` because it's useless with v3.0.0 firmware
150 |
151 | # v0.0.10
152 |
153 | ### New Function
154 |
155 | - Add `boardTypeForNumberOfChannels()` to Constants
156 |
157 | # v0.0.9
158 |
159 | ### New Features
160 |
161 | - Add impedance calculation functions from cyton
162 | - The simulator from OpenBCI_NodeJS has been ripped out and place into this library! Woo.
163 |
164 | # v0.0.8
165 |
166 | ### New Features
167 |
168 | - Sample object now has property `valid` of type `boolean`, `false` when error parseing packet, `true` otherwise. On `false` there will be another property called `error` of type `string` which contains an error message.
169 |
170 | # v0.0.7
171 |
172 | ### Continuous Integration
173 |
174 | - Add `npm run test-lint` to add linting to travis.yml
175 |
176 | ### Bug Fixes
177 |
178 | - Last sample number was confusing to use with `transformRawDataPacketsToSample`
179 |
180 | ### New Features
181 |
182 | - In openBCIUtilities.js add function `transformRawDataPacketToSample` to parse a single raw data packet
183 | - In openBCIConstants.js add function `rawDataToSampleObjectDefault(numChannels)` which should be used by drivers to create the object that is passed through each call to `transformRawDataPacketsToSample`
184 |
185 | # v0.0.6
186 |
187 | ### Bug Fixes
188 |
189 | - Could not use 'daisy' with sample rate setter.
190 |
191 | ### New Features
192 |
193 | - Add function in utilities for making daisy packets.
194 | - Add code to `getChannelDataArray` for ganglion and daisy data being routed over wifi
195 | - Create idea of protocols i.e. `BLE`, `Wifi`, and `Serial`
196 |
197 | ### Breaking changes
198 |
199 | - `getChannelDataArray` now takes object as only arg.
200 |
201 | # v0.0.5
202 |
203 | ### Bug Fixes
204 |
205 | - When not scaling outputs `channelDataCounts` instead of `channelData`
206 |
207 | # v0.0.4
208 |
209 | ### Bug Fixes
210 |
211 | - Fix bug where samples were not properly being extracted
212 |
213 | # v0.0.2
214 |
215 | ### Breaking Changes
216 |
217 | - Renamed `Sample` to `Utilities` in `index.js`
218 | - Renamed openBCIUtilities.js to openBCIUtilities.js
219 | - Renamed openBCIUtilities-test.js to openBCIUtilities-test.js
220 |
221 | ### New Features
222 |
223 | - Added a function in the sample module that parses a raw buffer of OpenBCI data, extracts raw data packets and returns the buffer with just the raw data packets removed. Allowing the user to process other data that is not a raw data.
224 |
225 | # v0.0.1
226 |
227 | Initial release
228 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # OpenBCI JavaScript Utilities Library Code of Conduct
2 |
3 | ## Purpose
4 |
5 | It is our hope that any one is able to contribute to OpenBCI JavaScript Utilities Library regardless of their background. Thus, we hope to provide a safe, welcoming, and warmly geeky environment for everybody, regardless of gender, sexual orientation, ability, ethnicity, socioeconomic status, and religion (or lack thereof).
6 |
7 | ## Our Standards
8 |
9 | Examples of behavior that contributes to creating a positive environment
10 | include:
11 |
12 | * Using welcoming and inclusive language
13 | * Being respectful of differing viewpoints and experiences
14 | * Gracefully accepting constructive criticism
15 | * Focusing on what is best for the community
16 | * Showing empathy towards other community members
17 |
18 | Examples of unacceptable behavior by participants include:
19 |
20 | * The use of sexualized language or imagery and unwelcome sexual attention or
21 | advances
22 | * Trolling, insulting/derogatory comments, and personal or political attacks
23 | * Public or private harassment
24 | * Publishing others' private information, such as a physical or electronic
25 | address, without explicit permission
26 | * Other conduct which could reasonably be considered inappropriate in a
27 | professional setting
28 |
29 | ## Our Responsibilities
30 |
31 | Project maintainers are responsible for clarifying the standards of acceptable
32 | behavior and are expected to take appropriate and fair corrective action in
33 | response to any instances of unacceptable behavior.
34 |
35 | Project maintainers have the right and responsibility to remove, edit, or
36 | reject comments, commits, code, wiki edits, issues, and other contributions
37 | that are not aligned to this Code of Conduct, or to ban temporarily or
38 | permanently any contributor for other behaviors that they deem inappropriate,
39 | threatening, offensive, or harmful.
40 |
41 | ## Scope
42 |
43 | This Code of Conduct applies both within project spaces and in public spaces
44 | when an individual is representing the project or its community. Examples of
45 | representing a project or community include using an official project e-mail
46 | address, posting via an official social media account, or acting as an appointed
47 | representative at an online or offline event. Representation of a project may be
48 | further defined and clarified by project maintainers.
49 |
50 | ## Enforcement
51 |
52 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
53 | reported by contacting the project team at [info@pushtheworld.us](mailto:info@pushtheworld.us). All
54 | complaints will be reviewed and investigated and will result in a response that
55 | is deemed necessary and appropriate to the circumstances. The project team is
56 | obligated to maintain confidentiality with regard to the reporter of an incident.
57 | Further details of specific enforcement policies may be posted separately.
58 |
59 | Project maintainers who do not follow or enforce the Code of Conduct in good
60 | faith may face temporary or permanent repercussions as determined by other
61 | members of the project's leadership.
62 |
63 | ## Attribution
64 |
65 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
66 | available at [http://contributor-covenant.org/version/1/4][version]
67 |
68 | [homepage]: http://contributor-covenant.org
69 | [version]: http://contributor-covenant.org/version/1/4/
70 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | :tada::clinking_glasses: First off, thanks for taking the time to contribute! :tada::clinking_glasses:
4 |
5 | Contributions are always welcome, no matter how small.
6 |
7 | The following is a small set of guidelines for how to contribute to the project
8 |
9 | ## Where to start
10 |
11 | ### Code of Conduct
12 | This project adheres to the Contributor Covenant [Code of Conduct](CODE_OF_CONDUCT.md).
13 | By participating you are expected to adhere to these expectations. Please report unacceptable behaviour to [info@pushtheworld.us](mailto:info@pushtheworld.us)
14 |
15 | ### Contributing on Github
16 |
17 | If you're new to Git and want to learn how to fork this repo, make your own additions, and include those additions in the master version of this project, check out this [great tutorial](http://blog.davidecoppola.com/2016/11/howto-contribute-to-open-source-project-on-github/).
18 |
19 | ### Community
20 |
21 | This project is maintained by the [OpenBCI](www.openbci.com) and [NeuroTechX](www.neurotechx.com) community. Join the NeuroTechX Slack to check out our #devices channel, where discussions about OpenBCI takes place.
22 |
23 | ## How can I contribute?
24 |
25 | This is currently a small, humble project so our contribution process is rather casual. Take a look at our [GitHub Projects board to see](https://github.com/NeuroTechX/eeg-101/projects) to see all the features we are currently working on. If there's a feature you'd be interested in building, go ahead! Let us know on the #interactive-tutorial channel on [the NeuroTechX Slack](http://neurotechx.herokuapp.com/) and we'll support you as much as we can. When you're finished submit a pull request to the master branch referencing the specific issue you addressed.
26 |
27 | If you find a bug, or have a suggestion on how to improve the project, just fill out a [Github issue](../../issues)
28 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 OpenBCI
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | **THIS REPOSITORY HAS BEEN DEPRECATED AND IS NO LONGER IN ACTIVE DEVELOPMENT.**
2 |
3 | # OpenBCI JavaScript Utilities Library
4 |
5 |
6 |
7 |
8 |
9 | Provide a stable javascript library for OpenBCI
10 |
11 |
12 | [](https://travis-ci.org/OpenBCI/OpenBCI_JavaScript_Utilities)
13 | [](https://codecov.io/gh/OpenBCI/OpenBCI_Javascript_Utilities)
14 | [](https://david-dm.org/OpenBCI/OpenBCI_Javascript_Utilities)
15 | [](http://npmjs.com/package/openbci-utilities)
16 | [](https://github.com/Flet/semistandard)
17 |
18 | ## Welcome!
19 |
20 | First and foremost, Welcome! :tada: Willkommen! :confetti_ball: Bienvenue! :balloon::balloon::balloon:
21 |
22 | Thank you for visiting the OpenBCI JavaScript Utilities Library repository.
23 |
24 | This document (the README file) is a hub to give you some information about the project. Jump straight to one of the sections below, or just scroll down to find out more.
25 |
26 | - [What are we doing? (And why?)](#what-are-we-doing)
27 | - [Who are we?](#who-are-we)
28 | - [What do we need?](#what-do-we-need)
29 | - [How can you get involved?](#get-involved)
30 | - [Get in touch](#contact-us)
31 | - [Find out more](#find-out-more)
32 | - [Understand the jargon](#glossary)
33 |
34 | ## What are we doing?
35 |
36 | ### The problem
37 |
38 | - The first javascript libraries for OpenBCI was the [NodeJS Cyton SDK][link_nodejs], then the [NodeJS Ganglion SDK][link_nodejs_ganglion], then the [NodeJS for WiFi][link_nodejs_wifi], each with their own interfaces, serial, bluetooth, and wifi respectively.
39 | - The ganglion's raw data is incredibly complex and must be decompressed and carefully parsed, in less words, it takes time to learn to parse this stream
40 | - People want to use the [Ganglion][link_shop_ganglion] in the web browser
41 |
42 | So, if even developers are interested in working with [OpenBCI][link_shop_openbci] devices with javascript, they have a huge burden to overcome before they can parse the data.
43 |
44 | ### The solution
45 |
46 | The OpenBCI JavaScript Utilities Library will:
47 |
48 | - Provide a nice cozy home to all the horror of parsing raw binary byte streams
49 | - Use automated testing extensively and don't let untested code be released!
50 | - Work in the browser and NodeJS!
51 | - Be able to parse ganglion and cyton data.
52 | - Store a constants file so every module agrees on names of keys and such
53 |
54 | Using a single unified JavaScript library solves the challenges of parsing raw brainwave data. Our main goal is to **_provide a stable javascript library for OpenBCI_**
55 |
56 | ## Who are we?
57 |
58 | The main code writer of the OpenBCI JavaScript Utilities Library is [AJ Keller][link_aj_keller]. This code all started in the OpenBCI NodeJS SDK for Cyton. Many people contributed, if not directly, but by advice or instructions drawn on a coffee table to calculate impedance. A lot of people who use this library never have any idea about it! Every user of the OpenBCI GUI is heavily dependent on this code base for all data acquisition from the Cyton, Ganglion and WiFi shield!
59 |
60 | ## What do we need?
61 |
62 | **You**! In whatever way you can help.
63 |
64 | We need expertise in programming, user experience, software sustainability, documentation and technical writing and project management.
65 |
66 | We'd love your feedback along the way.
67 |
68 | Our primary goal is to provide a stable javascript library for OpenBCI, and we're excited to support the professional development of any and all of our contributors. If you're looking to learn to code, try out working collaboratively, or translate you skills to the digital domain, we're here to help.
69 |
70 | ## Get involved
71 |
72 | If you think you can help in any of the areas listed above (and we bet you can) or in any of the many areas that we haven't yet thought of (and here we're _sure_ you can) then please check out our [contributors' guidelines](CONTRIBUTING.md) and our [roadmap](ROADMAP.md).
73 |
74 | Please note that it's very important to us that we maintain a positive and supportive environment for everyone who wants to participate. When you join us we ask that you follow our [code of conduct](CODE_OF_CONDUCT.md) in all interactions both on and offline.
75 |
76 | ## Contact us
77 |
78 | If you want to report a problem or suggest an enhancement we'd love for you to [open an issue](../../issues) at this github repository because then we can get right on it. But you can also contact [AJ][link_aj_keller] by email (pushtheworldllc AT gmail DOT com) or on [twitter](https://twitter.com/aj-ptw).
79 |
80 | ## Find out more
81 |
82 | You might be interested in:
83 |
84 | - What is [OpenBCI][link_openbci]?
85 |
86 | And of course, you'll want to know our:
87 |
88 | - [Contributors' guidelines](CONTRIBUTING.md)
89 | - [Roadmap](ROADMAP.md)
90 |
91 | ## Thank you
92 |
93 | Thank you so much (Danke schön! Merci beaucoup!) for visiting the project and we do hope that you'll join us on this amazing journey to make programming with OpenBCI fun and easy.
94 |
95 | # Documentation
96 |
97 | ### Table of Contents:
98 |
99 | ---
100 |
101 | 1. [Installation](#install)
102 | 2. [Usage](#usage)
103 | 3. [Developing](#developing)
104 | 4. [Testing](#developing-testing)
105 | 5. [Contribute](#contribute)
106 | 6. [License](#license)
107 |
108 | ## Installation:
109 |
110 | ```
111 | npm install @openbci/utilities
112 | ```
113 |
114 | ## Usage:
115 |
116 | ### In NodeJS
117 |
118 | ```node
119 | const { constants, debug, utilities } = require("openbci-utilities");
120 |
121 | console.log("OpenBCIUtilities", OpenBCIUtilities);
122 | ```
123 |
124 | ### In Web Browser
125 |
126 | **index.html**
127 |
128 | ```html
129 |
130 |
131 |
132 |
133 |
137 |
138 | OpenBCI Utilities
139 |
140 |
141 | See data in the console
142 |
143 |
144 |
145 |
146 | ```
147 |
148 | **index.js**
149 |
150 | ```javascript
151 | console.log(OpenBCIUtilities);
152 | ```
153 |
154 | ## Developing:
155 |
156 | ### Running:
157 |
158 | ```
159 | npm install
160 | ```
161 |
162 | ### Testing:
163 |
164 | ```
165 | npm test
166 | ```
167 |
168 | ## Contribute:
169 |
170 | 1. Fork it!
171 | 2. Branch off of `development`: `git checkout development`
172 | 3. Create your feature branch: `git checkout -b my-new-feature`
173 | 4. Make changes
174 | 5. If adding a feature, please add test coverage.
175 | 6. Ensure tests all pass. (`npm test`)
176 | 7. Commit your changes: `git commit -m 'Add some feature'`
177 | 8. Push to the branch: `git push origin my-new-feature`
178 | 9. Submit a pull request. Make sure it is based off of the `development` branch when submitting! :D
179 |
180 | ## License:
181 |
182 | MIT
183 |
184 | [link_aj_keller]: https://github.com/aj-ptw
185 | [link_shop_wifi_shield]: https://shop.openbci.com/collections/frontpage/products/wifi-shield?variant=44534009550
186 | [link_shop_ganglion]: https://shop.openbci.com/collections/frontpage/products/pre-order-ganglion-board
187 | [link_shop_cyton]: https://shop.openbci.com/collections/frontpage/products/cyton-biosensing-board-8-channel
188 | [link_shop_cyton_daisy]: https://shop.openbci.com/collections/frontpage/products/cyton-daisy-biosensing-boards-16-channel
189 | [link_nodejs]: https://github.com/OpenBCI/OpenBCI_NodeJS
190 | [link_nodejs_cyton]: https://github.com/OpenBCI/OpenBCI_NodeJS_Cyton
191 | [link_nodejs_ganglion]: https://github.com/OpenBCI/OpenBCI_NodeJS_Ganglion
192 | [link_nodejs_wifi]: https://github.com/OpenBCI/OpenBCI_NodeJS_Wifi
193 | [link_ptw]: https://www.pushtheworldllc.com
194 | [link_openbci]: http://www.openbci.com
195 | [link_mozwow]: http://mozillascience.github.io/working-open-workshop/index.html
196 | [link_wifi_get_streaming]: examples/getStreaming/getStreaming.js
197 | [link_openleaderscohort]: https://medium.com/@MozOpenLeaders
198 | [link_mozsci]: https://science.mozilla.org
199 |
--------------------------------------------------------------------------------
/ROADMAP.md:
--------------------------------------------------------------------------------
1 | # Roadmap
2 |
3 | ## OpenBCI JavaScript Utilities Library
4 |
5 | Provide a stable javascript library for OpenBCI
6 |
7 | ## Short term - what we're working on now
8 |
9 | - Unit tests!
10 | - Documentation for public functions
11 |
12 | ## Medium term
13 |
14 | - Examples
15 |
--------------------------------------------------------------------------------
/examples/browser/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | OpenBCI Utilities
8 |
9 |
10 | See data in the console
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/examples/browser/index.js:
--------------------------------------------------------------------------------
1 | console.log(OpenBCIUtilities); // eslint-disable-line
2 |
--------------------------------------------------------------------------------
/examples/node/index.js:
--------------------------------------------------------------------------------
1 | const OpenBCIUtilities = require("../..");
2 | const { constansts, debug, utilities } = require("../..");
3 |
4 | const { extractRawDataPackets } = require("../../dist/utilities");
5 | const OpenBCICnstants = require("../../dist/constants");
6 | const debug2 = require("../../dist/debug");
7 |
8 | console.log("OpenBCIUtilities", OpenBCIUtilities);
9 | console.log(
10 | "constansts, debug, utilities",
11 | constansts,
12 | debug,
13 | utilities
14 | );
15 | console.log("extractRawDataPackets", extractRawDataPackets);
16 | console.log("OpenBCICnstants", OpenBCICnstants);
17 | console.log("debug2", debug2);
18 |
--------------------------------------------------------------------------------
/images/node_icon2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openbci-archive/OpenBCI_JavaScript_Utilities/33168c60b530d1549b201150d6ce8bf69ac4dbb1/images/node_icon2.png
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@openbci/utilities",
3 | "version": "1.0.0",
4 | "description": "The official utility package of Node.js SDK for the OpenBCI Biosensor Boards.",
5 | "main": "dist/openbci-utilities.js",
6 | "module": "src/index.js",
7 | "scripts": {
8 | "build": "webpack",
9 | "start": "webpack-dev-server",
10 | "prepublish": "npm run build",
11 | "test": "npm run test-lint && npm run test-cov",
12 | "test-lint": "semistandard | snazzy",
13 | "test-cov": "istanbul cover ./node_modules/mocha/bin/_mocha -- -R spec && codecov"
14 | },
15 | "files": [
16 | "dist"
17 | ],
18 | "keywords": [
19 | "openbci",
20 | "openbci-node",
21 | "ganglion",
22 | "wifi",
23 | "cyton",
24 | "utilities"
25 | ],
26 | "author": "AJ Keller (www.openbci.com)",
27 | "license": "MIT",
28 | "dependencies": {
29 | "buffer": "^5.0.8",
30 | "buffer-equal": "^1.0.0",
31 | "clone": "^2.0.0",
32 | "gaussian": "^1.0.0",
33 | "mathjs": "^4.0.0",
34 | "performance-now": "^2.1.0",
35 | "streamsearch": "^0.1.2"
36 | },
37 | "directories": {
38 | "test": "test"
39 | },
40 | "devDependencies": {
41 | "babel-core": "^6.26.0",
42 | "babel-loader": "^7.1.2",
43 | "bluebird": "3.4.6",
44 | "chai": "^4.0.0",
45 | "chai-as-promised": "^7.1.1",
46 | "codecov": "^2.2.0",
47 | "dirty-chai": "^2.0.1",
48 | "eslint-plugin-chai-friendly": "^0.4.0",
49 | "istanbul": "^0.4.4",
50 | "lodash": "^4.16.6",
51 | "mocha": "^3.0.2",
52 | "sandboxed-module": "^2.0.3",
53 | "semistandard": "^11.0.0",
54 | "sinon": "^2.3.7",
55 | "sinon-chai": "^2.8.0",
56 | "snazzy": "^7.0.0",
57 | "webpack": "^3.8.1",
58 | "webpack-dev-server": "^2.9.3"
59 | },
60 | "repository": {
61 | "type": "git",
62 | "url": "git+https://github.com/openbci/openbci_nodejs_utilities.git"
63 | },
64 | "bugs": {
65 | "url": "https://github.com/openbci/openbci_nodejs_utilities/issues"
66 | },
67 | "homepage": "https://github.com/openbci/openbci_nodejs_utilities#readme",
68 | "engines": {
69 | "node": ">=6"
70 | },
71 | "semistandard": {
72 | "globals": [
73 | "describe",
74 | "xdescribe",
75 | "context",
76 | "before",
77 | "beforeEach",
78 | "after",
79 | "afterEach",
80 | "it",
81 | "expect",
82 | "should"
83 | ],
84 | "ignore": [
85 | "examples/browser",
86 | "examples/node"
87 | ]
88 | },
89 | "publishConfig": {
90 | "access": "public"
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/src/constants.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by ajk on 12/16/15.
3 | * Purpose: This file folds all the constants for the
4 | * OpenBCI Board
5 | */
6 | 'use strict';
7 | import { Buffer } from 'buffer/';
8 |
9 | /** Turning channels off */
10 | const obciChannelOff1 = '1';
11 | const obciChannelOff2 = '2';
12 | const obciChannelOff3 = '3';
13 | const obciChannelOff4 = '4';
14 | const obciChannelOff5 = '5';
15 | const obciChannelOff6 = '6';
16 | const obciChannelOff7 = '7';
17 | const obciChannelOff8 = '8';
18 | const obciChannelOff9 = 'q';
19 | const obciChannelOff10 = 'w';
20 | const obciChannelOff11 = 'e';
21 | const obciChannelOff12 = 'r';
22 | const obciChannelOff13 = 't';
23 | const obciChannelOff14 = 'y';
24 | const obciChannelOff15 = 'u';
25 | const obciChannelOff16 = 'i';
26 |
27 | /** Turn channels on */
28 | const obciChannelOn1 = '!';
29 | const obciChannelOn2 = '@';
30 | const obciChannelOn3 = '#';
31 | const obciChannelOn4 = '$';
32 | const obciChannelOn5 = '%';
33 | const obciChannelOn6 = '^';
34 | const obciChannelOn7 = '&';
35 | const obciChannelOn8 = '*';
36 | const obciChannelOn9 = 'Q';
37 | const obciChannelOn10 = 'W';
38 | const obciChannelOn11 = 'E';
39 | const obciChannelOn12 = 'R';
40 | const obciChannelOn13 = 'T';
41 | const obciChannelOn14 = 'Y';
42 | const obciChannelOn15 = 'U';
43 | const obciChannelOn16 = 'I';
44 |
45 | /** Test Signal Control Commands
46 | * 1x - Voltage will be 1 * (VREFP - VREFN) / 2.4 mV
47 | * 2x - Voltage will be 2 * (VREFP - VREFN) / 2.4 mV
48 | */
49 | const obciTestSignalConnectToDC = 'p';
50 | const obciTestSignalConnectToGround = '0';
51 | const obciTestSignalConnectToPulse1xFast = '=';
52 | const obciTestSignalConnectToPulse1xSlow = '-';
53 | const obciTestSignalConnectToPulse2xFast = ']';
54 | const obciTestSignalConnectToPulse2xSlow = '[';
55 |
56 | /** Channel Setting Commands */
57 | const obciChannelCmdADCNormal = '0';
58 | const obciChannelCmdADCShorted = '1';
59 | const obciChannelCmdADCBiasDRP = '6';
60 | const obciChannelCmdADCBiasDRN = '7';
61 | const obciChannelCmdADCBiasMethod = '2';
62 | const obciChannelCmdADCMVDD = '3';
63 | const obciChannelCmdADCTemp = '4';
64 | const obciChannelCmdADCTestSig = '5';
65 | const obciChannelCmdBiasInclude = '1';
66 | const obciChannelCmdBiasRemove = '0';
67 | const obciChannelCmdChannel1 = '1';
68 | const obciChannelCmdChannel2 = '2';
69 | const obciChannelCmdChannel3 = '3';
70 | const obciChannelCmdChannel4 = '4';
71 | const obciChannelCmdChannel5 = '5';
72 | const obciChannelCmdChannel6 = '6';
73 | const obciChannelCmdChannel7 = '7';
74 | const obciChannelCmdChannel8 = '8';
75 | const obciChannelCmdChannel9 = 'Q';
76 | const obciChannelCmdChannel10 = 'W';
77 | const obciChannelCmdChannel11 = 'E';
78 | const obciChannelCmdChannel12 = 'R';
79 | const obciChannelCmdChannel13 = 'T';
80 | const obciChannelCmdChannel14 = 'Y';
81 | const obciChannelCmdChannel15 = 'U';
82 | const obciChannelCmdChannel16 = 'I';
83 | const obciChannelCmdGain1 = '0';
84 | const obciChannelCmdGain2 = '1';
85 | const obciChannelCmdGain4 = '2';
86 | const obciChannelCmdGain6 = '3';
87 | const obciChannelCmdGain8 = '4';
88 | const obciChannelCmdGain12 = '5';
89 | const obciChannelCmdGain24 = '6';
90 | const obciChannelCmdLatch = 'X';
91 | const obciChannelCmdPowerOff = '1';
92 | const obciChannelCmdPowerOn = '0';
93 | const obciChannelCmdSet = 'x';
94 | const obciChannelCmdSRB1Connect = '1';
95 | const obciChannelCmdSRB1Diconnect = '0';
96 | const obciChannelCmdSRB2Connect = '1';
97 | const obciChannelCmdSRB2Diconnect = '0';
98 |
99 | /** Channel Setting Helper Strings */
100 | const obciStringADCNormal = 'normal';
101 | const obciStringADCShorted = 'shorted';
102 | const obciStringADCBiasMethod = 'biasMethod';
103 | const obciStringADCMvdd = 'mvdd';
104 | const obciStringADCTemp = 'temp';
105 | const obciStringADCTestSig = 'testSig';
106 | const obciStringADCBiasDrp = 'biasDrp';
107 | const obciStringADCBiasDrn = 'biasDrn';
108 |
109 | /** Default Channel Settings */
110 | const obciChannelDefaultAllSet = 'd';
111 | const obciChannelDefaultAllGet = 'D';
112 |
113 | /** LeadOff Impedance Commands */
114 | const obciChannelImpedanceLatch = 'Z';
115 | const obciChannelImpedanceSet = 'z';
116 | const obciChannelImpedanceTestSignalApplied = '1';
117 | const obciChannelImpedanceTestSignalAppliedNot = '0';
118 |
119 | /** SD card Commands */
120 | const obciSDLogForHour1 = 'G';
121 | const obciSDLogForHour2 = 'H';
122 | const obciSDLogForHour4 = 'J';
123 | const obciSDLogForHour12 = 'K';
124 | const obciSDLogForHour24 = 'L';
125 | const obciSDLogForMin5 = 'A';
126 | const obciSDLogForMin15 = 'S';
127 | const obciSDLogForMin30 = 'F';
128 | const obciSDLogForSec14 = 'a';
129 | const obciSDLogStop = 'j';
130 |
131 | /** SD Card String Commands */
132 | const obciStringSDHour1 = '1hour';
133 | const obciStringSDHour2 = '2hour';
134 | const obciStringSDHour4 = '4hour';
135 | const obciStringSDHour12 = '12hour';
136 | const obciStringSDHour24 = '24hour';
137 | const obciStringSDMin5 = '5min';
138 | const obciStringSDMin15 = '15min';
139 | const obciStringSDMin30 = '30min';
140 | const obciStringSDSec14 = '14sec';
141 |
142 | /** Stream Data Commands */
143 | const obciStreamStart = 'b';
144 | const obciStreamStop = 's';
145 |
146 | /** Miscellaneous */
147 | const obciMiscQueryRegisterSettings = '?';
148 | const obciMiscQueryRegisterSettingsChannel1 = 'CH1SET';
149 | const obciMiscQueryRegisterSettingsChannel2 = 'CH2SET';
150 | const obciMiscQueryRegisterSettingsChannel3 = 'CH3SET';
151 | const obciMiscQueryRegisterSettingsChannel4 = 'CH4SET';
152 | const obciMiscQueryRegisterSettingsChannel5 = 'CH5SET';
153 | const obciMiscQueryRegisterSettingsChannel6 = 'CH6SET';
154 | const obciMiscQueryRegisterSettingsChannel7 = 'CH7SET';
155 | const obciMiscQueryRegisterSettingsChannel8 = 'CH8SET';
156 | const obciMiscSoftReset = 'v';
157 |
158 | /** 16 Channel Commands */
159 | const obciChannelMaxNumber8 = 'c';
160 | const obciChannelMaxNumber16 = 'C';
161 | const obciChannelMaxNumber8NoDaisyToRemove = '';
162 | const obciChannelMaxNumber8SuccessDaisyRemoved = 'daisy removed';
163 | const obciChannelMaxNumber16DaisyAlreadyAttached = '16';
164 | const obciChannelMaxNumber16DaisyAttached = 'daisy attached16';
165 | const obciChannelMaxNumber16NoDaisyAttached = 'no daisy to attach!8';
166 |
167 | /** 60Hz line filter */
168 | const obciFilterDisable = 'g';
169 | const obciFilterEnable = 'f';
170 |
171 | /** Triggers */
172 | const obciTrigger = '`';
173 |
174 | /** Sync Clocks */
175 | const obciSyncTimeSet = '<';
176 | const obciSyncTimeSent = ',';
177 |
178 | /** Set board mode */
179 | const obciBoardModeSet = '/';
180 | const obciBoardModeCmdDefault = '0';
181 | const obciBoardModeCmdDebug = '1';
182 | const obciBoardModeCmdAnalog = '2';
183 | const obciBoardModeCmdDigital = '3';
184 | const obciBoardModeCmdGetCur = '/';
185 | const obciBoardModeAnalog = 'analog';
186 | const obciBoardModeDefault = 'default';
187 | const obciBoardModeDebug = 'debug';
188 | const obciBoardModeDigital = 'digital';
189 |
190 | /** Set sample rate */
191 | const obciSampleRateSet = '~';
192 | const obciSampleRateCmdCyton16000 = '0';
193 | const obciSampleRateCmdCyton8000 = '1';
194 | const obciSampleRateCmdCyton4000 = '2';
195 | const obciSampleRateCmdCyton2000 = '3';
196 | const obciSampleRateCmdCyton1000 = '4';
197 | const obciSampleRateCmdCyton500 = '5';
198 | const obciSampleRateCmdCyton250 = '6';
199 | const obciSampleRateCmdGang25600 = '0';
200 | const obciSampleRateCmdGang12800 = '1';
201 | const obciSampleRateCmdGang6400 = '2';
202 | const obciSampleRateCmdGang3200 = '3';
203 | const obciSampleRateCmdGang1600 = '4';
204 | const obciSampleRateCmdGang800 = '5';
205 | const obciSampleRateCmdGang400 = '6';
206 | const obciSampleRateCmdGang200 = '7';
207 | const obciSampleRateCmdaGetCur = '~';
208 |
209 | /** Accel enable/disable commands */
210 | const obciAccelStart = 'n';
211 | const obciAccelStop = 'N';
212 |
213 | /** Wifi Stuff */
214 | const obciWifiAttach = '{';
215 | const obciWifiRemove = '}';
216 | const obciWifiReset = ';';
217 | const obciWifiStatus = ':';
218 |
219 | /** Radio Key */
220 | const obciRadioKey = 0xF0;
221 | /** Radio Commands */
222 | const obciRadioCmdChannelGet = 0x00;
223 | const obciRadioCmdChannelSet = 0x01;
224 | const obciRadioCmdChannelSetOverride = 0x02;
225 | const obciRadioCmdPollTimeGet = 0x03;
226 | const obciRadioCmdPollTimeSet = 0x04;
227 | const obciRadioCmdBaudRateSetDefault = 0x05;
228 | const obciRadioCmdBaudRateSetFast = 0x06;
229 | const obciRadioCmdSystemStatus = 0x07;
230 |
231 | /** Possible number of channels */
232 | const obciNumberOfChannelsCyton = 8;
233 | const obciNumberOfChannelsCytonBLE = 2;
234 | const obciNumberOfChannelsDaisy = 16;
235 | const obciNumberOfChannelsDefault = obciNumberOfChannelsCyton;
236 | const obciNumberOfChannelsGanglion = 4;
237 |
238 | /** Possible OpenBCI board types */
239 | const obciBoardCyton = 'cyton';
240 | const obciBoardCytonBLE = 'cytonBLE';
241 | const obciBoardDaisy = 'daisy';
242 | const obciBoardDefault = 'default';
243 | const obciBoardGanglion = 'ganglion';
244 | const obciBoardNone = 'none';
245 |
246 | /** Possible Simulator Line Noise injections */
247 | const obciSimulatorLineNoiseHz60 = '60Hz';
248 | const obciSimulatorLineNoiseHz50 = '50Hz';
249 | const obciSimulatorLineNoiseNone = 'none';
250 |
251 | /** Possible Simulator Fragmentation modes */
252 | const obciSimulatorFragmentationRandom = 'random';
253 | const obciSimulatorFragmentationFullBuffers = 'fullBuffers';
254 | const obciSimulatorFragmentationOneByOne = 'oneByOne';
255 | const obciSimulatorFragmentationNone = 'none';
256 |
257 | /** Possible Sample Rates */
258 | const obciSampleRate1000 = 1000;
259 | const obciSampleRate125 = 125;
260 | const obciSampleRate12800 = 12800;
261 | const obciSampleRate1600 = 1600;
262 | const obciSampleRate16000 = 16000;
263 | const obciSampleRate200 = 200;
264 | const obciSampleRate2000 = 2000;
265 | const obciSampleRate250 = 250;
266 | const obciSampleRate25600 = 25600;
267 | const obciSampleRate3200 = 3200;
268 | const obciSampleRate400 = 400;
269 | const obciSampleRate4000 = 4000;
270 | const obciSampleRate500 = 500;
271 | const obciSampleRate6400 = 6400;
272 | const obciSampleRate800 = 800;
273 | const obciSampleRate8000 = 8000;
274 |
275 | /** Max sample number */
276 | const obciSampleNumberMax = 255;
277 |
278 | /** Packet Size */
279 | const obciPacketSize = 33;
280 | const obciPacketSizeBLECyton = 20;
281 | const obciPacketSizeBLERaw = 12;
282 |
283 | /** OpenBCI V3 Standard Packet Positions */
284 | /**
285 | * 0:[startByte] | 1:[sampleNumber] | 2:[Channel-1.1] | 3:[Channel-1.2] | 4:[Channel-1.3] | 5:[Channel-2.1] | 6:[Channel-2.2] | 7:[Channel-2.3] | 8:[Channel-3.1] | 9:[Channel-3.2] | 10:[Channel-3.3] | 11:[Channel-4.1] | 12:[Channel-4.2] | 13:[Channel-4.3] | 14:[Channel-5.1] | 15:[Channel-5.2] | 16:[Channel-5.3] | 17:[Channel-6.1] | 18:[Channel-6.2] | 19:[Channel-6.3] | 20:[Channel-7.1] | 21:[Channel-7.2] | 22:[Channel-7.3] | 23:[Channel-8.1] | 24:[Channel-8.2] | 25:[Channel-8.3] | 26:[Aux-1.1] | 27:[Aux-1.2] | 28:[Aux-2.1] | 29:[Aux-2.2] | 30:[Aux-3.1] | 31:[Aux-3.2] | 32:StopByte
286 | */
287 | const obciPacketPositionChannelDataStart = 2; // 0:startByte | 1:sampleNumber | [2:4] | [5:7] | [8:10] | [11:13] | [14:16] | [17:19] | [21:23] | [24:26]
288 | const obciPacketPositionChannelDataStop = 25; // 24 bytes for channel data
289 | const obciPacketPositionSampleNumber = 1;
290 | const obciPacketPositionStartByte = 0; // first byte
291 | const obciPacketPositionStopByte = 32; // [32]
292 | const obciPacketPositionStartAux = 26; // [26,27]:Aux 1 | [28,29]:Aux 2 | [30,31]:Aux 3
293 | const obciPacketPositionStopAux = 31; // - - - [30,31]:Aux 3 | 32: Stop byte
294 | const obciPacketPositionTimeSyncAuxStart = 26;
295 | const obciPacketPositionTimeSyncAuxStop = 28;
296 | const obciPacketPositionTimeSyncTimeStart = 28;
297 | const obciPacketPositionTimeSyncTimeStop = 32;
298 |
299 | /** Notable Bytes */
300 | const obciByteStart = 0xA0;
301 | const obciByteStop = 0xC0;
302 |
303 | /** Errors */
304 | const errorInvalidByteLength = 'Invalid Packet Byte Length';
305 | const errorInvalidByteStart = 'Invalid Start Byte';
306 | const errorInvalidByteStop = 'Invalid Stop Byte';
307 | const errorInvalidData = 'Invalid data - try again';
308 | const errorInvalidType = 'Invalid type - check comments for input type';
309 | const errorMissingRegisterSetting = 'Missing register setting';
310 | const errorMissingRequiredProperty = 'Missing property in JSON';
311 | const errorNobleAlreadyScanning = 'Scan already under way';
312 | const errorNobleNotAlreadyScanning = 'No scan started';
313 | const errorNobleNotInPoweredOnState = 'Please turn blue tooth on.';
314 | const errorTimeSyncIsNull = "'this.sync.curSyncObj' must not be null";
315 | const errorTimeSyncNoComma = 'Missed the time sync sent confirmation. Try sync again';
316 | const errorUndefinedOrNullInput = 'Undefined or Null Input';
317 |
318 | /** Max Master Buffer Size */
319 | const obciMasterBufferSize = 4096;
320 |
321 | /** Impedance Calculation Variables */
322 | const obciLeadOffDriveInAmps = 0.000000006;
323 | const obciLeadOffFrequencyHz = 31.5;
324 |
325 | /** Command send delay */
326 | const obciWriteIntervalDelayMSLong = 50;
327 | const obciWriteIntervalDelayMSNone = 0;
328 | const obciWriteIntervalDelayMSShort = 10;
329 |
330 | /** Impedance */
331 | const obciImpedanceTextBad = 'bad';
332 | const obciImpedanceTextNone = 'none';
333 | const obciImpedanceTextGood = 'good';
334 | const obciImpedanceTextInit = 'init';
335 | const obciImpedanceTextOk = 'ok';
336 |
337 | const obciImpedanceThresholdGoodMin = 0;
338 | const obciImpedanceThresholdGoodMax = 5000;
339 | const obciImpedanceThresholdOkMin = 5001;
340 | const obciImpedanceThresholdOkMax = 10000;
341 | const obciImpedanceThresholdBadMin = 10001;
342 | const obciImpedanceThresholdBadMax = 1000000;
343 |
344 | const obciImpedanceSeriesResistor = 2200; // There is a 2.2 k Ohm series resistor that must be subtracted
345 |
346 | /** Simulator */
347 | const obciSimulatorPortName = 'OpenBCISimulator';
348 |
349 | /**
350 | * Stream packet types/codes
351 | */
352 | const obciStreamPacketStandardAccel = 0; // 0000
353 | const obciStreamPacketStandardRawAux = 1; // 0001
354 | const obciStreamPacketUserDefinedType = 2; // 0010
355 | const obciStreamPacketAccelTimeSyncSet = 3; // 0011
356 | const obciStreamPacketAccelTimeSynced = 4; // 0100
357 | const obciStreamPacketRawAuxTimeSyncSet = 5; // 0101
358 | const obciStreamPacketRawAuxTimeSynced = 6; // 0110
359 | const obciStreamPacketImpedance = 7; // 0111
360 |
361 | /** Time from board */
362 | const obciStreamPacketTimeByteSize = 4;
363 |
364 | /** Time synced with accel packet */
365 | const obciAccelAxisX = 7;
366 | const obciAccelAxisY = 8;
367 | const obciAccelAxisZ = 9;
368 |
369 | /** Firmware version indicator */
370 | const obciFirmwareV1 = 'v1';
371 | const obciFirmwareV2 = 'v2';
372 | const obciFirmwareV3 = 'v3';
373 |
374 | /** Parse */
375 | const obciParseDaisy = 'Daisy';
376 | const obciParseFirmware = 'v2';
377 | const obciParseFailure = 'Failure';
378 | const obciParseEOT = '$$$';
379 | const obciParseSuccess = 'Success';
380 |
381 | /** Used in parsing incoming serial data */
382 | const obciParsingChannelSettings = 2;
383 | const obciParsingEOT = 4;
384 | const obciParsingNormal = 3;
385 | const obciParsingReset = 0;
386 | const obciParsingTimeSyncSent = 1;
387 |
388 | /** Timeouts */
389 | const obciTimeoutProcessBytes = 500; // 0.5 seconds
390 |
391 | /** Simulator Board Configurations */
392 | const obciSimulatorRawAux = 'rawAux';
393 | const obciSimulatorStandard = 'standard';
394 |
395 | /** OpenBCI Radio Limits */
396 | const obciRadioChannelMax = 25;
397 | const obciRadioChannelMin = 1;
398 | const obciRadioPollTimeMax = 255;
399 | const obciRadioPollTimeMin = 0;
400 |
401 | /** Time sync stuff */
402 | const obciTimeSyncArraySize = 10;
403 | const obciTimeSyncMultiplierWithSyncConf = 0.9;
404 | const obciTimeSyncMultiplierWithoutSyncConf = 0.75;
405 | const obciTimeSyncThresholdTransFailureMS = 10; // ms
406 |
407 | /** Baud Rates */
408 | const obciRadioBaudRateDefault = 115200;
409 | const obciRadioBaudRateDefaultStr = 'default';
410 | const obciRadioBaudRateFast = 230400;
411 | const obciRadioBaudRateFastStr = 'fast';
412 |
413 | /** Emitters */
414 | const obciEmitterAccelerometer = 'accelerometer';
415 | const obciEmitterBlePoweredUp = 'blePoweredOn';
416 | const obciEmitterClose = 'close';
417 | const obciEmitterDroppedPacket = 'droppedPacket';
418 | const obciEmitterEot = 'eot';
419 | const obciEmitterError = 'error';
420 | const obciEmitterGanglionFound = 'ganglionFound';
421 | const obciEmitterHardSet = 'hardSet';
422 | const obciEmitterImpedance = 'impedance';
423 | const obciEmitterImpedanceArray = 'impedanceArray';
424 | const obciEmitterMessage = 'message';
425 | const obciEmitterQuery = 'query';
426 | const obciEmitterRawDataPacket = 'rawDataPacket';
427 | const obciEmitterReady = 'ready';
428 | const obciEmitterRFduino = 'rfduino';
429 | const obciEmitterSample = 'sample';
430 | const obciEmitterScanStopped = 'scanStopped';
431 | const obciEmitterSynced = 'synced';
432 | const obciEmitterWifiShield = 'wifiShield';
433 |
434 | /** Accel packets */
435 | const obciGanglionAccelAxisX = 1;
436 | const obciGanglionAccelAxisY = 2;
437 | const obciGanglionAccelAxisZ = 3;
438 |
439 | /** Accel scale factor */
440 | const obciGanglionAccelScaleFactor = 0.016; // mG per count
441 |
442 | /** Ganglion */
443 | const obciGanglionBleSearchTime = 20000; // ms
444 | const obciGanglionByteIdUncompressed = 0;
445 | const obciGanglionByteId18Bit = {
446 | max: 100,
447 | min: 1
448 | };
449 | const obciGanglionByteId19Bit = {
450 | max: 200,
451 | min: 101
452 | };
453 | const obciGanglionByteIdImpedanceChannel1 = 201;
454 | const obciGanglionByteIdImpedanceChannel2 = 202;
455 | const obciGanglionByteIdImpedanceChannel3 = 203;
456 | const obciGanglionByteIdImpedanceChannel4 = 204;
457 | const obciGanglionByteIdImpedanceChannelReference = 205;
458 | const obciGanglionByteIdMultiPacket = 206;
459 | const obciGanglionByteIdMultiPacketStop = 207;
460 | const obciGanglionPacketSize = 20;
461 | const obciGanglionSamplesPerPacket = 2;
462 | const obciGanglionPacket18Bit = {
463 | auxByte: 20,
464 | byteId: 0,
465 | dataStart: 1,
466 | dataStop: 19
467 | };
468 | const obciGanglionPacket19Bit = {
469 | byteId: 0,
470 | dataStart: 1,
471 | dataStop: 20
472 | };
473 | const obciGanglionMCP3912Gain = 51.0; // assumed gain setting for MCP3912. NEEDS TO BE ADJUSTABLE JM
474 | const obciGanglionMCP3912Vref = 1.2; // reference voltage for ADC in MCP3912 set in hardware
475 | const obciGanglionPrefix = 'Ganglion';
476 | const obciGanglionSyntheticDataEnable = 't';
477 | const obciGanglionSyntheticDataDisable = 'T';
478 | const obciGanglionImpedanceStart = 'z';
479 | const obciGanglionImpedanceStop = 'Z';
480 | const obciGanglionScaleFactorPerCountVolts = obciGanglionMCP3912Vref / (8388607.0 * obciGanglionMCP3912Gain * 1.5);
481 |
482 | /** Simblee */
483 | const simbleeUuidService = 'fe84';
484 | const simbleeUuidReceive = '2d30c082f39f4ce6923f3484ea480596';
485 | const simbleeUuidSend = '2d30c083f39f4ce6923f3484ea480596';
486 | const simbleeUuidDisconnect = '2d30c084f39f4ce6923f3484ea480596';
487 |
488 | /** RFduino BLE UUID */
489 | const rfduinoUuidService = '2220';
490 | const rfduinoUuidReceive = '2221';
491 | const rfduinoUuidSend = '2222';
492 | const rfduinoUuidSendTwo = '2223';
493 |
494 | /** Cyton BLE */
495 | const obciCytonBLESamplesPerPacket = 3;
496 |
497 | /** Noble */
498 | const obciNobleEmitterPeripheralConnect = 'connect';
499 | const obciNobleEmitterPeripheralDisconnect = 'disconnect';
500 | const obciNobleEmitterPeripheralDiscover = 'discover';
501 | const obciNobleEmitterPeripheralServicesDiscover = 'servicesDiscover';
502 | const obciNobleEmitterServiceCharacteristicsDiscover = 'characteristicsDiscover';
503 | const obciNobleEmitterServiceRead = 'read';
504 | const obciNobleEmitterDiscover = 'discover';
505 | const obciNobleEmitterScanStart = 'scanStart';
506 | const obciNobleEmitterScanStop = 'scanStop';
507 | const obciNobleEmitterStateChange = 'stateChange';
508 | const obciNobleStatePoweredOn = 'poweredOn';
509 |
510 | /** Protocols */
511 | const obciProtocolBLE = 'ble';
512 | const obciProtocolSerial = 'serial';
513 | const obciProtocolWifi = 'wifi';
514 |
515 | /** Register Query on Cyton */
516 | const obciRegisterQueryAccelerometerFirmwareV1 = '\nLIS3DH Registers\n0x07.0\n0x08.0\n0x09.0\n0x0A.0\n0x0B.0\n0x0C.0\n0x0D.0\n0x0E.0\n0x0F.33\n\n0x1F.0\n0x20.8\n0x21.0\n0x22.0\n0x23.18\n0x24.0\n0x25.0\n0x26.0\n0x27.0\n0x28.0\n0x29.0\n0x2A.0\n0x2B.0\n0x2C.0\n0x2D.0\n0x2E.0\n0x2F.20\n0x30.0\n0x31.0\n0x32.0\n0x33.0\n\n0x38.0\n0x39.0\n0x3A.0\n0x3B.0\n0x3C.0\n0x3D.0\n';
517 | const obciRegisterQueryAccelerometerFirmwareV3 = '\nLIS3DH Registers\n0x07 00\n0x08 00\n0x09 00\n0x0A 00\n0x0B 00\n0x0C 00\n0x0D 00\n0x0E 00\n0x0F 33\n\n0x1F 00\n0x20 08\n0x21 00\n0x22 00\n0x23 18\n0x24 00\n0x25 00\n0x26 00\n0x27 00\n0x28 00\n0x29 00\n0x2A 00\n0x2B 00\n0x2C 00\n0x2D 00\n0x2E 00\n0x2F 20\n0x30 00\n0x31 00\n0x32 00\n0x33 00\n\n0x38 00\n0x39 00\n0x3A 00\n0x3B 00\n0x3C 00\n0x3D 00\n';
518 | const obciRegisterQueryCyton = '\nBoard ADS Registers\nADS_ID, 00, 3E, 0, 0, 1, 1, 1, 1, 1, 0\nCONFIG1, 01, 96, 1, 0, 0, 1, 0, 1, 1, 0\nCONFIG2, 02, C0, 1, 1, 0, 0, 0, 0, 0, 0\nCONFIG3, 03, EC, 1, 1, 1, 0, 1, 1, 0, 0\nLOFF, 04, 02, 0, 0, 0, 0, 0, 0, 1, 0\nCH1SET, 05, 68, 0, 1, 1, 0, 1, 0, 0, 0\nCH2SET, 06, 68, 0, 1, 1, 0, 1, 0, 0, 0\nCH3SET, 07, 68, 0, 1, 1, 0, 1, 0, 0, 0\nCH4SET, 08, 68, 0, 1, 1, 0, 1, 0, 0, 0\nCH5SET, 09, 68, 0, 1, 1, 0, 1, 0, 0, 0\nCH6SET, 0A, 68, 0, 1, 1, 0, 1, 0, 0, 0\nCH7SET, 0B, 68, 0, 1, 1, 0, 1, 0, 0, 0\nCH8SET, 0C, 68, 0, 1, 1, 0, 1, 0, 0, 0\nBIAS_SENSP, 0D, FF, 1, 1, 1, 1, 1, 1, 1, 1\nBIAS_SENSN, 0E, FF, 1, 1, 1, 1, 1, 1, 1, 1\nLOFF_SENSP, 0F, 00, 0, 0, 0, 0, 0, 0, 0, 0\nLOFF_SENSN, 10, 00, 0, 0, 0, 0, 0, 0, 0, 0\nLOFF_FLIP, 11, 00, 0, 0, 0, 0, 0, 0, 0, 0\nLOFF_STATP, 12, 00, 0, 0, 0, 0, 0, 0, 0, 0\nLOFF_STATN, 13, 00, 0, 0, 0, 0, 0, 0, 0, 0\nGPIO, 14, 0F, 0, 0, 0, 0, 1, 1, 1, 1\nMISC1, 15, 00, 0, 0, 0, 0, 0, 0, 0, 0\nMISC2, 16, 00, 0, 0, 0, 0, 0, 0, 0, 0\nCONFIG4, 17, 00, 0, 0, 0, 0, 0, 0, 0, 0\n';
519 | const obciRegisterQueryCytonDaisy = '\nDaisy ADS Registers\nADS_ID, 00, 3E, 0, 0, 1, 1, 1, 1, 1, 0\nCONFIG1, 01, 96, 1, 0, 0, 1, 0, 1, 1, 0\nCONFIG2, 02, C0, 1, 1, 0, 0, 0, 0, 0, 0\nCONFIG3, 03, EC, 1, 1, 1, 0, 1, 1, 0, 0\nLOFF, 04, 02, 0, 0, 0, 0, 0, 0, 1, 0\nCH1SET, 05, 68, 0, 1, 1, 0, 1, 0, 0, 0\nCH2SET, 06, 68, 0, 1, 1, 0, 1, 0, 0, 0\nCH3SET, 07, 68, 0, 1, 1, 0, 1, 0, 0, 0\nCH4SET, 08, 68, 0, 1, 1, 0, 1, 0, 0, 0\nCH5SET, 09, 68, 0, 1, 1, 0, 1, 0, 0, 0\nCH6SET, 0A, 68, 0, 1, 1, 0, 1, 0, 0, 0\nCH7SET, 0B, 68, 0, 1, 1, 0, 1, 0, 0, 0\nCH8SET, 0C, 68, 0, 1, 1, 0, 1, 0, 0, 0\nBIAS_SENSP, 0D, FF, 1, 1, 1, 1, 1, 1, 1, 1\nBIAS_SENSN, 0E, FF, 1, 1, 1, 1, 1, 1, 1, 1\nLOFF_SENSP, 0F, 00, 0, 0, 0, 0, 0, 0, 0, 0\nLOFF_SENSN, 10, 00, 0, 0, 0, 0, 0, 0, 0, 0\nLOFF_FLIP, 11, 00, 0, 0, 0, 0, 0, 0, 0, 0\nLOFF_STATP, 12, 00, 0, 0, 0, 0, 0, 0, 0, 0\nLOFF_STATN, 13, 00, 0, 0, 0, 0, 0, 0, 0, 0\nGPIO, 14, 0F, 0, 0, 0, 0, 1, 1, 1, 1\nMISC1, 15, 00, 0, 0, 0, 0, 0, 0, 0, 0\nMISC2, 16, 00, 0, 0, 0, 0, 0, 0, 0, 0\nCONFIG4, 17, 00, 0, 0, 0, 0, 0, 0, 0, 0\n';
520 | const obciRegisterQueryNameMISC1 = 'MISC1';
521 | const obciRegisterQueryNameBIASSENSP = 'BIAS_SENSP';
522 | const obciRegisterQueryNameCHnSET = ['CH1SET', 'CH2SET', 'CH3SET', 'CH4SET', 'CH5SET', 'CH6SET', 'CH7SET', 'CH8SET'];
523 | const obciRegisterQuerySizeCytonFirmwareV1 = obciRegisterQueryCyton.length + obciRegisterQueryAccelerometerFirmwareV1.length;
524 | const obciRegisterQuerySizeCytonDaisyFirmwareV1 = obciRegisterQueryCyton.length + obciRegisterQueryCytonDaisy.length + obciRegisterQueryAccelerometerFirmwareV1.length;
525 | const obciRegisterQuerySizeCytonFirmwareV3 = obciRegisterQueryCyton.length + obciRegisterQueryAccelerometerFirmwareV3.length;
526 | const obciRegisterQuerySizeCytonDaisyFirmwareV3 = obciRegisterQueryCyton.length + obciRegisterQueryCytonDaisy.length + obciRegisterQueryAccelerometerFirmwareV3.length;
527 |
528 | const constantsModule = {
529 | /** Turning channels off */
530 | OBCIChannelOff1: obciChannelOff1,
531 | OBCIChannelOff2: obciChannelOff2,
532 | OBCIChannelOff3: obciChannelOff3,
533 | OBCIChannelOff4: obciChannelOff4,
534 | OBCIChannelOff5: obciChannelOff5,
535 | OBCIChannelOff6: obciChannelOff6,
536 | OBCIChannelOff7: obciChannelOff7,
537 | OBCIChannelOff8: obciChannelOff8,
538 | OBCIChannelOff9: obciChannelOff9,
539 | OBCIChannelOff10: obciChannelOff10,
540 | OBCIChannelOff11: obciChannelOff11,
541 | OBCIChannelOff12: obciChannelOff12,
542 | OBCIChannelOff13: obciChannelOff13,
543 | OBCIChannelOff14: obciChannelOff14,
544 | OBCIChannelOff15: obciChannelOff15,
545 | OBCIChannelOff16: obciChannelOff16,
546 | /**
547 | * Purpose: To get the proper command to turn a channel off
548 | * @param channelNumber - A number (1-16) of the desired channel
549 | * @returns {Promise}
550 | */
551 | commandChannelOff: function (channelNumber) {
552 | return new Promise(function (resolve, reject) {
553 | switch (channelNumber) {
554 | case 1:
555 | resolve(obciChannelOff1);
556 | break;
557 | case 2:
558 | resolve(obciChannelOff2);
559 | break;
560 | case 3:
561 | resolve(obciChannelOff3);
562 | break;
563 | case 4:
564 | resolve(obciChannelOff4);
565 | break;
566 | case 5:
567 | resolve(obciChannelOff5);
568 | break;
569 | case 6:
570 | resolve(obciChannelOff6);
571 | break;
572 | case 7:
573 | resolve(obciChannelOff7);
574 | break;
575 | case 8:
576 | resolve(obciChannelOff8);
577 | break;
578 | case 9:
579 | resolve(obciChannelOff9);
580 | break;
581 | case 10:
582 | resolve(obciChannelOff10);
583 | break;
584 | case 11:
585 | resolve(obciChannelOff11);
586 | break;
587 | case 12:
588 | resolve(obciChannelOff12);
589 | break;
590 | case 13:
591 | resolve(obciChannelOff13);
592 | break;
593 | case 14:
594 | resolve(obciChannelOff14);
595 | break;
596 | case 15:
597 | resolve(obciChannelOff15);
598 | break;
599 | case 16:
600 | resolve(obciChannelOff16);
601 | break;
602 | default:
603 | reject(Error('Error [commandChannelOff]: Invalid Channel Number'));
604 | break;
605 | }
606 | });
607 | },
608 | /** Turning channels on */
609 | OBCIChannelOn1: obciChannelOn1,
610 | OBCIChannelOn2: obciChannelOn2,
611 | OBCIChannelOn3: obciChannelOn3,
612 | OBCIChannelOn4: obciChannelOn4,
613 | OBCIChannelOn5: obciChannelOn5,
614 | OBCIChannelOn6: obciChannelOn6,
615 | OBCIChannelOn7: obciChannelOn7,
616 | OBCIChannelOn8: obciChannelOn8,
617 | OBCIChannelOn9: obciChannelOn9,
618 | OBCIChannelOn10: obciChannelOn10,
619 | OBCIChannelOn11: obciChannelOn11,
620 | OBCIChannelOn12: obciChannelOn12,
621 | OBCIChannelOn13: obciChannelOn13,
622 | OBCIChannelOn14: obciChannelOn14,
623 | OBCIChannelOn15: obciChannelOn15,
624 | OBCIChannelOn16: obciChannelOn16,
625 | commandChannelOn: function (channelNumber) {
626 | return new Promise(function (resolve, reject) {
627 | switch (channelNumber) {
628 | case 1:
629 | resolve(obciChannelOn1);
630 | break;
631 | case 2:
632 | resolve(obciChannelOn2);
633 | break;
634 | case 3:
635 | resolve(obciChannelOn3);
636 | break;
637 | case 4:
638 | resolve(obciChannelOn4);
639 | break;
640 | case 5:
641 | resolve(obciChannelOn5);
642 | break;
643 | case 6:
644 | resolve(obciChannelOn6);
645 | break;
646 | case 7:
647 | resolve(obciChannelOn7);
648 | break;
649 | case 8:
650 | resolve(obciChannelOn8);
651 | break;
652 | case 9:
653 | resolve(obciChannelOn9);
654 | break;
655 | case 10:
656 | resolve(obciChannelOn10);
657 | break;
658 | case 11:
659 | resolve(obciChannelOn11);
660 | break;
661 | case 12:
662 | resolve(obciChannelOn12);
663 | break;
664 | case 13:
665 | resolve(obciChannelOn13);
666 | break;
667 | case 14:
668 | resolve(obciChannelOn14);
669 | break;
670 | case 15:
671 | resolve(obciChannelOn15);
672 | break;
673 | case 16:
674 | resolve(obciChannelOn16);
675 | break;
676 | default:
677 | reject(Error('Error [commandChannelOn]: Invalid Channel Number'));
678 | break;
679 | }
680 | });
681 | },
682 | /** Test Signal Control Commands */
683 | OBCITestSignalConnectToDC: obciTestSignalConnectToDC,
684 | OBCITestSignalConnectToGround: obciTestSignalConnectToGround,
685 | OBCITestSignalConnectToPulse1xFast: obciTestSignalConnectToPulse1xFast,
686 | OBCITestSignalConnectToPulse1xSlow: obciTestSignalConnectToPulse1xSlow,
687 | OBCITestSignalConnectToPulse2xFast: obciTestSignalConnectToPulse2xFast,
688 | OBCITestSignalConnectToPulse2xSlow: obciTestSignalConnectToPulse2xSlow,
689 | getTestSignalCommand: (signal) => {
690 | return new Promise((resolve, reject) => {
691 | switch (signal) {
692 | case 'dc':
693 | resolve(obciTestSignalConnectToDC);
694 | break;
695 | case 'ground':
696 | resolve(obciTestSignalConnectToGround);
697 | break;
698 | case 'pulse1xFast':
699 | resolve(obciTestSignalConnectToPulse1xFast);
700 | break;
701 | case 'pulse1xSlow':
702 | resolve(obciTestSignalConnectToPulse1xSlow);
703 | break;
704 | case 'pulse2xFast':
705 | resolve(obciTestSignalConnectToPulse2xFast);
706 | break;
707 | case 'pulse2xSlow':
708 | resolve(obciTestSignalConnectToPulse2xSlow);
709 | break;
710 | case 'none':
711 | resolve(obciChannelDefaultAllSet);
712 | break;
713 | default:
714 | reject(Error('Invalid selection! Check your spelling.'));
715 | break;
716 | }
717 | });
718 | },
719 | /** Channel Setting Commands */
720 | OBCIChannelCmdADCNormal: obciChannelCmdADCNormal,
721 | OBCIChannelCmdADCShorted: obciChannelCmdADCShorted,
722 | OBCIChannelCmdADCBiasDRP: obciChannelCmdADCBiasDRP,
723 | OBCIChannelCmdADCBiasDRN: obciChannelCmdADCBiasDRN,
724 | OBCIChannelCmdADCBiasMethod: obciChannelCmdADCBiasMethod,
725 | OBCIChannelCmdADCMVDD: obciChannelCmdADCMVDD,
726 | OBCIChannelCmdADCTemp: obciChannelCmdADCTemp,
727 | OBCIChannelCmdADCTestSig: obciChannelCmdADCTestSig,
728 | OBCIChannelCmdBiasInclude: obciChannelCmdBiasInclude,
729 | OBCIChannelCmdBiasRemove: obciChannelCmdBiasRemove,
730 | OBCIChannelCmdChannel1: obciChannelCmdChannel1,
731 | OBCIChannelCmdChannel2: obciChannelCmdChannel2,
732 | OBCIChannelCmdChannel3: obciChannelCmdChannel3,
733 | OBCIChannelCmdChannel4: obciChannelCmdChannel4,
734 | OBCIChannelCmdChannel5: obciChannelCmdChannel5,
735 | OBCIChannelCmdChannel6: obciChannelCmdChannel6,
736 | OBCIChannelCmdChannel7: obciChannelCmdChannel7,
737 | OBCIChannelCmdChannel8: obciChannelCmdChannel8,
738 | OBCIChannelCmdChannel9: obciChannelCmdChannel9,
739 | OBCIChannelCmdChannel10: obciChannelCmdChannel10,
740 | OBCIChannelCmdChannel11: obciChannelCmdChannel11,
741 | OBCIChannelCmdChannel12: obciChannelCmdChannel12,
742 | OBCIChannelCmdChannel13: obciChannelCmdChannel13,
743 | OBCIChannelCmdChannel14: obciChannelCmdChannel14,
744 | OBCIChannelCmdChannel15: obciChannelCmdChannel15,
745 | OBCIChannelCmdChannel16: obciChannelCmdChannel16,
746 | commandChannelForCmd,
747 | OBCIChannelCmdGain1: obciChannelCmdGain1,
748 | OBCIChannelCmdGain2: obciChannelCmdGain2,
749 | OBCIChannelCmdGain4: obciChannelCmdGain4,
750 | OBCIChannelCmdGain6: obciChannelCmdGain6,
751 | OBCIChannelCmdGain8: obciChannelCmdGain8,
752 | OBCIChannelCmdGain12: obciChannelCmdGain12,
753 | OBCIChannelCmdGain24: obciChannelCmdGain24,
754 | commandForGain,
755 | gainForCommand,
756 | OBCIChannelCmdLatch: obciChannelCmdLatch,
757 | OBCIChannelCmdPowerOff: obciChannelCmdPowerOff,
758 | OBCIChannelCmdPowerOn: obciChannelCmdPowerOn,
759 | OBCIChannelCmdSet: obciChannelCmdSet,
760 | OBCIChannelCmdSRB1Connect: obciChannelCmdSRB1Connect,
761 | OBCIChannelCmdSRB1Diconnect: obciChannelCmdSRB1Diconnect,
762 | OBCIChannelCmdSRB2Connect: obciChannelCmdSRB2Connect,
763 | OBCIChannelCmdSRB2Diconnect: obciChannelCmdSRB2Diconnect,
764 | /** Channel Settings Object */
765 | channelSettingsObjectDefault,
766 | /**
767 | * @param numberOfChannels {Number}
768 | * @returns {Array}
769 | */
770 | channelSettingsArrayInit: (numberOfChannels) => {
771 | var newChannelSettingsArray = [];
772 | for (var i = 0; i < numberOfChannels; i++) {
773 | newChannelSettingsArray.push(channelSettingsObjectDefault(i));
774 | }
775 | return newChannelSettingsArray;
776 | },
777 | /** Channel Setting Helper Strings */
778 | OBCIStringADCNormal: obciStringADCNormal,
779 | OBCIStringADCShorted: obciStringADCShorted,
780 | OBCIStringADCBiasMethod: obciStringADCBiasMethod,
781 | OBCIStringADCMvdd: obciStringADCMvdd,
782 | OBCIStringADCTemp: obciStringADCTemp,
783 | OBCIStringADCTestSig: obciStringADCTestSig,
784 | OBCIStringADCBiasDrp: obciStringADCBiasDrp,
785 | OBCIStringADCBiasDrn: obciStringADCBiasDrn,
786 | /**
787 | * @description To convert a string like 'normal' to the correct command (i.e. '1')
788 | * @param adcString
789 | * @returns {Promise}
790 | * @author AJ Keller (@pushtheworldllc)
791 | */
792 | commandForADCString,
793 | inputTypeForCommand,
794 | /** Default Channel Settings */
795 | OBCIChannelDefaultAllSet: obciChannelDefaultAllSet,
796 | OBCIChannelDefaultAllGet: obciChannelDefaultAllGet,
797 | /** LeadOff Impedance Commands */
798 | OBCIChannelImpedanceLatch: obciChannelImpedanceLatch,
799 | OBCIChannelImpedanceSet: obciChannelImpedanceSet,
800 | OBCIChannelImpedanceTestSignalApplied: obciChannelImpedanceTestSignalApplied,
801 | OBCIChannelImpedanceTestSignalAppliedNot: obciChannelImpedanceTestSignalAppliedNot,
802 | /** SD card Commands */
803 | OBCISDLogForHour1: obciSDLogForHour1,
804 | OBCISDLogForHour2: obciSDLogForHour2,
805 | OBCISDLogForHour4: obciSDLogForHour4,
806 | OBCISDLogForHour12: obciSDLogForHour12,
807 | OBCISDLogForHour24: obciSDLogForHour24,
808 | OBCISDLogForMin5: obciSDLogForMin5,
809 | OBCISDLogForMin15: obciSDLogForMin15,
810 | OBCISDLogForMin30: obciSDLogForMin30,
811 | OBCISDLogForSec14: obciSDLogForSec14,
812 | OBCISDLogStop: obciSDLogStop,
813 | /** SD Card String Commands */
814 | OBCIStringSDHour1: obciStringSDHour1,
815 | OBCIStringSDHour2: obciStringSDHour2,
816 | OBCIStringSDHour4: obciStringSDHour4,
817 | OBCIStringSDHour12: obciStringSDHour12,
818 | OBCIStringSDHour24: obciStringSDHour24,
819 | OBCIStringSDMin5: obciStringSDMin5,
820 | OBCIStringSDMin15: obciStringSDMin15,
821 | OBCIStringSDMin30: obciStringSDMin30,
822 | OBCIStringSDSec14: obciStringSDSec14,
823 | /**
824 | * @description Converts a sd string into the proper setting.
825 | * @param stringCommand {String} - The length of time you want to record to the SD for.
826 | * @returns {Promise} The command to send to the Board, returns an error on improper `stringCommand`
827 | */
828 | sdSettingForString: (stringCommand) => {
829 | return new Promise((resolve, reject) => {
830 | switch (stringCommand) {
831 | case obciStringSDHour1:
832 | resolve(obciSDLogForHour1);
833 | break;
834 | case obciStringSDHour2:
835 | resolve(obciSDLogForHour2);
836 | break;
837 | case obciStringSDHour4:
838 | resolve(obciSDLogForHour4);
839 | break;
840 | case obciStringSDHour12:
841 | resolve(obciSDLogForHour12);
842 | break;
843 | case obciStringSDHour24:
844 | resolve(obciSDLogForHour24);
845 | break;
846 | case obciStringSDMin5:
847 | resolve(obciSDLogForMin5);
848 | break;
849 | case obciStringSDMin15:
850 | resolve(obciSDLogForMin15);
851 | break;
852 | case obciStringSDMin30:
853 | resolve(obciSDLogForMin30);
854 | break;
855 | case obciStringSDSec14:
856 | resolve(obciSDLogForSec14);
857 | break;
858 | default:
859 | reject(Error(TypeError));
860 | break;
861 | }
862 | });
863 | },
864 | /** Stream Data Commands */
865 | OBCIStreamStart: obciStreamStart,
866 | OBCIStreamStop: obciStreamStop,
867 | /** Accel enable/disable commands */
868 | OBCIAccelStart: obciAccelStart,
869 | OBCIAccelStop: obciAccelStop,
870 | /** Miscellaneous */
871 | OBCIMiscQueryRegisterSettings: obciMiscQueryRegisterSettings,
872 | OBCIMiscQueryRegisterSettingsChannel1: obciMiscQueryRegisterSettingsChannel1,
873 | OBCIMiscQueryRegisterSettingsChannel2: obciMiscQueryRegisterSettingsChannel2,
874 | OBCIMiscQueryRegisterSettingsChannel3: obciMiscQueryRegisterSettingsChannel3,
875 | OBCIMiscQueryRegisterSettingsChannel4: obciMiscQueryRegisterSettingsChannel4,
876 | OBCIMiscQueryRegisterSettingsChannel5: obciMiscQueryRegisterSettingsChannel5,
877 | OBCIMiscQueryRegisterSettingsChannel6: obciMiscQueryRegisterSettingsChannel6,
878 | OBCIMiscQueryRegisterSettingsChannel7: obciMiscQueryRegisterSettingsChannel7,
879 | OBCIMiscQueryRegisterSettingsChannel8: obciMiscQueryRegisterSettingsChannel8,
880 | channelSettingsKeyForChannel: channelNumber => {
881 | return new Promise((resolve, reject) => {
882 | switch (channelNumber) {
883 | case 1:
884 | resolve(new Buffer(obciMiscQueryRegisterSettingsChannel1));
885 | break;
886 | case 2:
887 | resolve(new Buffer(obciMiscQueryRegisterSettingsChannel2));
888 | break;
889 | case 3:
890 | resolve(new Buffer(obciMiscQueryRegisterSettingsChannel3));
891 | break;
892 | case 4:
893 | resolve(new Buffer(obciMiscQueryRegisterSettingsChannel4));
894 | break;
895 | case 5:
896 | resolve(new Buffer(obciMiscQueryRegisterSettingsChannel5));
897 | break;
898 | case 6:
899 | resolve(new Buffer(obciMiscQueryRegisterSettingsChannel6));
900 | break;
901 | case 7:
902 | resolve(new Buffer(obciMiscQueryRegisterSettingsChannel7));
903 | break;
904 | case 8:
905 | resolve(new Buffer(obciMiscQueryRegisterSettingsChannel8));
906 | break;
907 | default:
908 | reject(Error('Invalid channel number'));
909 | break;
910 | }
911 | });
912 | },
913 | OBCIMiscSoftReset: obciMiscSoftReset,
914 | /** 16 Channel Commands */
915 | OBCIChannelMaxNumber8: obciChannelMaxNumber8,
916 | OBCIChannelMaxNumber16: obciChannelMaxNumber16,
917 | OBCIChannelMaxNumber8NoDaisyToRemove: obciChannelMaxNumber8NoDaisyToRemove,
918 | OBCIChannelMaxNumber8SuccessDaisyRemoved: obciChannelMaxNumber8SuccessDaisyRemoved,
919 | OBCIChannelMaxNumber16DaisyAlreadyAttached: obciChannelMaxNumber16DaisyAlreadyAttached,
920 | OBCIChannelMaxNumber16DaisyAttached: obciChannelMaxNumber16DaisyAttached,
921 | OBCIChannelMaxNumber16NoDaisyAttached: obciChannelMaxNumber16NoDaisyAttached,
922 | /** Filters */
923 | OBCIFilterDisable: obciFilterDisable,
924 | OBCIFilterEnable: obciFilterEnable,
925 | /** Triggers */
926 | OBCITrigger: obciTrigger,
927 | /** Possible number of channels */
928 | OBCINumberOfChannelsCyton: obciNumberOfChannelsCyton,
929 | OBCINumberOfChannelsCytonBLE: obciNumberOfChannelsCytonBLE,
930 | OBCINumberOfChannelsDaisy: obciNumberOfChannelsDaisy,
931 | OBCINumberOfChannelsDefault: obciNumberOfChannelsDefault,
932 | OBCINumberOfChannelsGanglion: obciNumberOfChannelsGanglion,
933 | /** Possible OpenBCI board types */
934 | OBCIBoardCyton: obciBoardCyton,
935 | OBCIBoardCytonBLE: obciBoardCytonBLE,
936 | OBCIBoardDaisy: obciBoardDaisy,
937 | OBCIBoardDefault: obciBoardDefault,
938 | OBCIBoardGanglion: obciBoardGanglion,
939 | OBCIBoardNone: obciBoardNone,
940 | numberOfChannelsForBoardType: boardType => {
941 | switch (boardType) {
942 | case obciBoardDaisy:
943 | return obciNumberOfChannelsDaisy;
944 | case obciBoardGanglion:
945 | return obciNumberOfChannelsGanglion;
946 | case obciBoardNone:
947 | return 0;
948 | case obciBoardCytonBLE:
949 | return obciNumberOfChannelsCytonBLE;
950 | case obciBoardCyton:
951 | default:
952 | return obciNumberOfChannelsDefault;
953 | }
954 | },
955 | boardTypeForNumberOfChannels: (numberOfChannels) => {
956 | switch (numberOfChannels) {
957 | case obciNumberOfChannelsDaisy:
958 | return obciBoardDaisy;
959 | case obciNumberOfChannelsGanglion:
960 | return obciBoardGanglion;
961 | case 0:
962 | return obciBoardNone;
963 | case obciNumberOfChannelsCytonBLE:
964 | return obciBoardCytonBLE;
965 | case obciNumberOfChannelsDefault:
966 | default:
967 | return obciBoardCyton;
968 | }
969 | },
970 | /** Possible Sample Rates */
971 | OBCISampleRate1000: obciSampleRate1000,
972 | OBCISampleRate125: obciSampleRate125,
973 | OBCISampleRate12800: obciSampleRate12800,
974 | OBCISampleRate1600: obciSampleRate1600,
975 | OBCISampleRate16000: obciSampleRate16000,
976 | OBCISampleRate200: obciSampleRate200,
977 | OBCISampleRate2000: obciSampleRate2000,
978 | OBCISampleRate250: obciSampleRate250,
979 | OBCISampleRate25600: obciSampleRate25600,
980 | OBCISampleRate3200: obciSampleRate3200,
981 | OBCISampleRate400: obciSampleRate400,
982 | OBCISampleRate4000: obciSampleRate4000,
983 | OBCISampleRate500: obciSampleRate500,
984 | OBCISampleRate6400: obciSampleRate6400,
985 | OBCISampleRate800: obciSampleRate800,
986 | OBCISampleRate8000: obciSampleRate8000,
987 | /** Max sample number */
988 | OBCISampleNumberMax: obciSampleNumberMax,
989 | /** Packet Size */
990 | OBCIPacketSize: obciPacketSize,
991 | OBCIPacketSizeBLECyton: obciPacketSizeBLECyton,
992 | OBCIPacketSizeBLERaw: obciPacketSizeBLERaw,
993 | /** Notable Bytes */
994 | OBCIByteStart: obciByteStart,
995 | OBCIByteStop: obciByteStop,
996 | /** Errors */
997 | OBCIErrorInvalidByteLength: errorInvalidByteLength,
998 | OBCIErrorInvalidByteStart: errorInvalidByteStart,
999 | OBCIErrorInvalidByteStop: errorInvalidByteStop,
1000 | OBCIErrorInvalidData: errorInvalidData,
1001 | OBCIErrorInvalidType: errorInvalidType,
1002 | OBCIErrorMissingRegisterSetting: errorMissingRegisterSetting,
1003 | OBCIErrorMissingRequiredProperty: errorMissingRequiredProperty,
1004 | OBCIErrorNobleAlreadyScanning: errorNobleAlreadyScanning,
1005 | OBCIErrorNobleNotAlreadyScanning: errorNobleNotAlreadyScanning,
1006 | OBCIErrorNobleNotInPoweredOnState: errorNobleNotInPoweredOnState,
1007 | OBCIErrorTimeSyncIsNull: errorTimeSyncIsNull,
1008 | OBCIErrorTimeSyncNoComma: errorTimeSyncNoComma,
1009 | OBCIErrorUndefinedOrNullInput: errorUndefinedOrNullInput,
1010 | /** Max Master Buffer Size */
1011 | OBCIMasterBufferSize: obciMasterBufferSize,
1012 | /** Impedance Calculation Variables */
1013 | OBCILeadOffDriveInAmps: obciLeadOffDriveInAmps,
1014 | OBCILeadOffFrequencyHz: obciLeadOffFrequencyHz,
1015 | /** Channel Setter Maker */
1016 | getChannelSetter: channelSetter,
1017 | /** Impedance Setter Maker */
1018 | getImpedanceSetter: impedanceSetter,
1019 | /** Sample Rate Setter Maker */
1020 | getSampleRateSetter: sampleRateSetter,
1021 | /** Board Mode Setter Maker */
1022 | getBoardModeSetter: boardModeSetter,
1023 | /** Command send delay */
1024 | OBCIWriteIntervalDelayMSLong: obciWriteIntervalDelayMSLong,
1025 | OBCIWriteIntervalDelayMSNone: obciWriteIntervalDelayMSNone,
1026 | OBCIWriteIntervalDelayMSShort: obciWriteIntervalDelayMSShort,
1027 | /** Sync Clocks */
1028 | OBCISyncTimeSent: obciSyncTimeSent,
1029 | OBCISyncTimeSet: obciSyncTimeSet,
1030 | /** Radio Key */
1031 | OBCIRadioKey: obciRadioKey,
1032 | /** Radio Commands */
1033 | OBCIRadioCmdChannelGet: obciRadioCmdChannelGet,
1034 | OBCIRadioCmdChannelSet: obciRadioCmdChannelSet,
1035 | OBCIRadioCmdChannelSetOverride: obciRadioCmdChannelSetOverride,
1036 | OBCIRadioCmdPollTimeGet: obciRadioCmdPollTimeGet,
1037 | OBCIRadioCmdPollTimeSet: obciRadioCmdPollTimeSet,
1038 | OBCIRadioCmdBaudRateSetDefault: obciRadioCmdBaudRateSetDefault,
1039 | OBCIRadioCmdBaudRateSetFast: obciRadioCmdBaudRateSetFast,
1040 | OBCIRadioCmdSystemStatus: obciRadioCmdSystemStatus,
1041 | /** Impedance */
1042 | OBCIImpedanceTextBad: obciImpedanceTextBad,
1043 | OBCIImpedanceTextGood: obciImpedanceTextGood,
1044 | OBCIImpedanceTextInit: obciImpedanceTextInit,
1045 | OBCIImpedanceTextOk: obciImpedanceTextOk,
1046 | OBCIImpedanceTextNone: obciImpedanceTextNone,
1047 | OBCIImpedanceThresholdBadMax: obciImpedanceThresholdBadMax,
1048 | OBCIImpedanceSeriesResistor: obciImpedanceSeriesResistor,
1049 | getTextForRawImpedance: (value) => {
1050 | if (value > obciImpedanceThresholdGoodMin && value < obciImpedanceThresholdGoodMax) {
1051 | return obciImpedanceTextGood;
1052 | } else if (value > obciImpedanceThresholdOkMin && value < obciImpedanceThresholdOkMax) {
1053 | return obciImpedanceTextOk;
1054 | } else if (value > obciImpedanceThresholdBadMin && value < obciImpedanceThresholdBadMax) {
1055 | return obciImpedanceTextBad;
1056 | } else {
1057 | return obciImpedanceTextNone;
1058 | }
1059 | },
1060 | /** Simulator */
1061 | OBCISimulatorPortName: obciSimulatorPortName,
1062 | /**
1063 | * Stream packet types/codes
1064 | */
1065 | OBCIStreamPacketStandardAccel: obciStreamPacketStandardAccel,
1066 | OBCIStreamPacketStandardRawAux: obciStreamPacketStandardRawAux,
1067 | OBCIStreamPacketUserDefinedType: obciStreamPacketUserDefinedType,
1068 | OBCIStreamPacketAccelTimeSyncSet: obciStreamPacketAccelTimeSyncSet,
1069 | OBCIStreamPacketAccelTimeSynced: obciStreamPacketAccelTimeSynced,
1070 | OBCIStreamPacketRawAuxTimeSyncSet: obciStreamPacketRawAuxTimeSyncSet,
1071 | OBCIStreamPacketRawAuxTimeSynced: obciStreamPacketRawAuxTimeSynced,
1072 | OBCIStreamPacketImpedance: obciStreamPacketImpedance,
1073 | /** fun funcs */
1074 | isNumber,
1075 | isBoolean,
1076 | isString,
1077 | isUndefined,
1078 | isNull,
1079 | /** OpenBCI V3 Standard Packet Positions */
1080 | OBCIPacketPositionStartByte: obciPacketPositionStartByte,
1081 | OBCIPacketPositionStopByte: obciPacketPositionStopByte,
1082 | OBCIPacketPositionStartAux: obciPacketPositionStartAux,
1083 | OBCIPacketPositionStopAux: obciPacketPositionStopAux,
1084 | OBCIPacketPositionChannelDataStart: obciPacketPositionChannelDataStart,
1085 | OBCIPacketPositionChannelDataStop: obciPacketPositionChannelDataStop,
1086 | OBCIPacketPositionSampleNumber: obciPacketPositionSampleNumber,
1087 | OBCIPacketPositionTimeSyncAuxStart: obciPacketPositionTimeSyncAuxStart,
1088 | OBCIPacketPositionTimeSyncAuxStop: obciPacketPositionTimeSyncAuxStop,
1089 | OBCIPacketPositionTimeSyncTimeStart: obciPacketPositionTimeSyncTimeStart,
1090 | OBCIPacketPositionTimeSyncTimeStop: obciPacketPositionTimeSyncTimeStop,
1091 | /** Possible Simulator Line Noise injections */
1092 | OBCISimulatorLineNoiseHz60: obciSimulatorLineNoiseHz60,
1093 | OBCISimulatorLineNoiseHz50: obciSimulatorLineNoiseHz50,
1094 | OBCISimulatorLineNoiseNone: obciSimulatorLineNoiseNone,
1095 | /** Possible Simulator Fragmentation modes */
1096 | OBCISimulatorFragmentationRandom: obciSimulatorFragmentationRandom,
1097 | OBCISimulatorFragmentationFullBuffers: obciSimulatorFragmentationFullBuffers,
1098 | OBCISimulatorFragmentationOneByOne: obciSimulatorFragmentationOneByOne,
1099 | OBCISimulatorFragmentationNone: obciSimulatorFragmentationNone,
1100 | /** Firmware version indicator */
1101 | OBCIFirmwareV1: obciFirmwareV1,
1102 | OBCIFirmwareV2: obciFirmwareV2,
1103 | OBCIFirmwareV3: obciFirmwareV3,
1104 | /** Time synced accel packet */
1105 | OBCIAccelAxisX: obciAccelAxisX,
1106 | OBCIAccelAxisY: obciAccelAxisY,
1107 | OBCIAccelAxisZ: obciAccelAxisZ,
1108 | /** Time from board */
1109 | OBCIStreamPacketTimeByteSize: obciStreamPacketTimeByteSize,
1110 | /** Parse */
1111 | OBCIParseDaisy: obciParseDaisy,
1112 | OBCIParseFailure: obciParseFailure,
1113 | OBCIParseFirmware: obciParseFirmware,
1114 | OBCIParseEOT: obciParseEOT,
1115 | OBCIParseSuccess: obciParseSuccess,
1116 | /** Used in parsing incoming serial data */
1117 | OBCIParsingChannelSettings: obciParsingChannelSettings,
1118 | OBCIParsingEOT: obciParsingEOT,
1119 | OBCIParsingNormal: obciParsingNormal,
1120 | OBCIParsingReset: obciParsingReset,
1121 | OBCIParsingTimeSyncSent: obciParsingTimeSyncSent,
1122 | /** Timeouts */
1123 | OBCITimeoutProcessBytes: obciTimeoutProcessBytes,
1124 | /** Simulator Board Configurations */
1125 | OBCISimulatorRawAux: obciSimulatorRawAux,
1126 | OBCISimulatorStandard: obciSimulatorStandard,
1127 | /** Radio Channel Limits */
1128 | OBCIRadioChannelMax: obciRadioChannelMax,
1129 | OBCIRadioChannelMin: obciRadioChannelMin,
1130 | OBCIRadioPollTimeMax: obciRadioPollTimeMax,
1131 | OBCIRadioPollTimeMin: obciRadioPollTimeMin,
1132 | /** Time sync stuff */
1133 | OBCITimeSyncArraySize: obciTimeSyncArraySize,
1134 | OBCITimeSyncMultiplierWithSyncConf: obciTimeSyncMultiplierWithSyncConf,
1135 | OBCITimeSyncMultiplierWithoutSyncConf: obciTimeSyncMultiplierWithoutSyncConf,
1136 | OBCITimeSyncThresholdTransFailureMS: obciTimeSyncThresholdTransFailureMS,
1137 | /** Set board mode */
1138 | OBCIBoardModeSet: obciBoardModeSet,
1139 | OBCIBoardModeCmdDefault: obciBoardModeCmdDefault,
1140 | OBCIBoardModeCmdDebug: obciBoardModeCmdDebug,
1141 | OBCIBoardModeCmdAnalog: obciBoardModeCmdAnalog,
1142 | OBCIBoardModeCmdDigital: obciBoardModeCmdDigital,
1143 | OBCIBoardModeCmdGetCur: obciBoardModeCmdGetCur,
1144 | OBCIBoardModeAnalog: obciBoardModeAnalog,
1145 | OBCIBoardModeDefault: obciBoardModeDefault,
1146 | OBCIBoardModeDebug: obciBoardModeDebug,
1147 | OBCIBoardModeDigital: obciBoardModeDigital,
1148 |
1149 | /** Set sample rate */
1150 | OBCISampleRateSet: obciSampleRateSet,
1151 | OBCISampleRateCmdCyton16000: obciSampleRateCmdCyton16000,
1152 | OBCISampleRateCmdCyton8000: obciSampleRateCmdCyton8000,
1153 | OBCISampleRateCmdCyton4000: obciSampleRateCmdCyton4000,
1154 | OBCISampleRateCmdCyton2000: obciSampleRateCmdCyton2000,
1155 | OBCISampleRateCmdCyton1000: obciSampleRateCmdCyton1000,
1156 | OBCISampleRateCmdCyton500: obciSampleRateCmdCyton500,
1157 | OBCISampleRateCmdCyton250: obciSampleRateCmdCyton250,
1158 | OBCISampleRateCmdGang25600: obciSampleRateCmdGang25600,
1159 | OBCISampleRateCmdGang12800: obciSampleRateCmdGang12800,
1160 | OBCISampleRateCmdGang6400: obciSampleRateCmdGang6400,
1161 | OBCISampleRateCmdGang3200: obciSampleRateCmdGang3200,
1162 | OBCISampleRateCmdGang1600: obciSampleRateCmdGang1600,
1163 | OBCISampleRateCmdGang800: obciSampleRateCmdGang800,
1164 | OBCISampleRateCmdGang400: obciSampleRateCmdGang400,
1165 | OBCISampleRateCmdGang200: obciSampleRateCmdGang200,
1166 | OBCISampleRateCmdGetCur: obciSampleRateCmdaGetCur,
1167 |
1168 | /** Wifi Stuff */
1169 | OBCIWifiAttach: obciWifiAttach,
1170 | OBCIWifiRemove: obciWifiRemove,
1171 | OBCIWifiReset: obciWifiReset,
1172 | OBCIWifiStatus: obciWifiStatus,
1173 | /** Baud Rates */
1174 | OBCIRadioBaudRateDefault: obciRadioBaudRateDefault,
1175 | OBCIRadioBaudRateDefaultStr: obciRadioBaudRateDefaultStr,
1176 | OBCIRadioBaudRateFast: obciRadioBaudRateFast,
1177 | OBCIRadioBaudRateFastStr: obciRadioBaudRateFastStr,
1178 | /** Emitters */
1179 | OBCIEmitterAccelerometer: obciEmitterAccelerometer,
1180 | OBCIEmitterBlePoweredUp: obciEmitterBlePoweredUp,
1181 | OBCIEmitterClose: obciEmitterClose,
1182 | OBCIEmitterDroppedPacket: obciEmitterDroppedPacket,
1183 | OBCIEmitterEot: obciEmitterEot,
1184 | OBCIEmitterError: obciEmitterError,
1185 | OBCIEmitterGanglionFound: obciEmitterGanglionFound,
1186 | OBCIEmitterHardSet: obciEmitterHardSet,
1187 | OBCIEmitterImpedance: obciEmitterImpedance,
1188 | OBCIEmitterImpedanceArray: obciEmitterImpedanceArray,
1189 | OBCIEmitterMessage: obciEmitterMessage,
1190 | OBCIEmitterQuery: obciEmitterQuery,
1191 | OBCIEmitterRawDataPacket: obciEmitterRawDataPacket,
1192 | OBCIEmitterReady: obciEmitterReady,
1193 | OBCIEmitterRFduino: obciEmitterRFduino,
1194 | OBCIEmitterSample: obciEmitterSample,
1195 | OBCIEmitterScanStopped: obciEmitterScanStopped,
1196 | OBCIEmitterSynced: obciEmitterSynced,
1197 | OBCIEmitterWifiShield: obciEmitterWifiShield,
1198 | /** Emitters */
1199 | /** Accel packets */
1200 | OBCIGanglionAccelAxisX: obciGanglionAccelAxisX,
1201 | OBCIGanglionAccelAxisY: obciGanglionAccelAxisY,
1202 | OBCIGanglionAccelAxisZ: obciGanglionAccelAxisZ,
1203 | /** Ganglion */
1204 | OBCIGanglionBleSearchTime: obciGanglionBleSearchTime,
1205 | OBCIGanglionByteIdUncompressed: obciGanglionByteIdUncompressed,
1206 | OBCIGanglionByteId18Bit: obciGanglionByteId18Bit,
1207 | OBCIGanglionByteId19Bit: obciGanglionByteId19Bit,
1208 | OBCIGanglionByteIdImpedanceChannel1: obciGanglionByteIdImpedanceChannel1,
1209 | OBCIGanglionByteIdImpedanceChannel2: obciGanglionByteIdImpedanceChannel2,
1210 | OBCIGanglionByteIdImpedanceChannel3: obciGanglionByteIdImpedanceChannel3,
1211 | OBCIGanglionByteIdImpedanceChannel4: obciGanglionByteIdImpedanceChannel4,
1212 | OBCIGanglionByteIdImpedanceChannelReference: obciGanglionByteIdImpedanceChannelReference,
1213 | OBCIGanglionByteIdMultiPacket: obciGanglionByteIdMultiPacket,
1214 | OBCIGanglionByteIdMultiPacketStop: obciGanglionByteIdMultiPacketStop,
1215 | OBCIGanglionMCP3912Gain: obciGanglionMCP3912Gain, // assumed gain setting for MCP3912. NEEDS TO BE ADJUSTABLE JM
1216 | OBCIGanglionMCP3912Vref: obciGanglionMCP3912Vref, // reference voltage for ADC in MCP3912 set in hardware
1217 | OBCIGanglionPacketSize: obciGanglionPacketSize,
1218 | OBCIGanglionPacket18Bit: obciGanglionPacket18Bit,
1219 | OBCIGanglionPacket19Bit: obciGanglionPacket19Bit,
1220 | OBCIGanglionPrefix: obciGanglionPrefix,
1221 | OBCIGanglionSamplesPerPacket: obciGanglionSamplesPerPacket,
1222 | OBCIGanglionSyntheticDataEnable: obciGanglionSyntheticDataEnable,
1223 | OBCIGanglionSyntheticDataDisable: obciGanglionSyntheticDataDisable,
1224 | OBCIGanglionImpedanceStart: obciGanglionImpedanceStart,
1225 | OBCIGanglionImpedanceStop: obciGanglionImpedanceStop,
1226 | OBCIGanglionScaleFactorPerCountVolts: obciGanglionScaleFactorPerCountVolts,
1227 | /** Simblee */
1228 | SimbleeUuidService: simbleeUuidService,
1229 | SimbleeUuidReceive: simbleeUuidReceive,
1230 | SimbleeUuidSend: simbleeUuidSend,
1231 | SimbleeUuidDisconnect: simbleeUuidDisconnect,
1232 | /** RFduino BLE UUID */
1233 | RFduinoUuidService: rfduinoUuidService,
1234 | RFduinoUuidReceive: rfduinoUuidReceive,
1235 | RFduinoUuidSend: rfduinoUuidSend,
1236 | RFduinoUuidSendTwo: rfduinoUuidSendTwo,
1237 | /** Cyton BLE */
1238 | OBCICytonBLESamplesPerPacket: obciCytonBLESamplesPerPacket,
1239 | /** Accel scale factor */
1240 | OBCIGanglionAccelScaleFactor: obciGanglionAccelScaleFactor,
1241 | /** Noble */
1242 | OBCINobleEmitterPeripheralConnect: obciNobleEmitterPeripheralConnect,
1243 | OBCINobleEmitterPeripheralDisconnect: obciNobleEmitterPeripheralDisconnect,
1244 | OBCINobleEmitterPeripheralDiscover: obciNobleEmitterPeripheralDiscover,
1245 | OBCINobleEmitterPeripheralServicesDiscover: obciNobleEmitterPeripheralServicesDiscover,
1246 | OBCINobleEmitterServiceCharacteristicsDiscover: obciNobleEmitterServiceCharacteristicsDiscover,
1247 | OBCINobleEmitterServiceRead: obciNobleEmitterServiceRead,
1248 | OBCINobleEmitterDiscover: obciNobleEmitterDiscover,
1249 | OBCINobleEmitterScanStart: obciNobleEmitterScanStart,
1250 | OBCINobleEmitterScanStop: obciNobleEmitterScanStop,
1251 | OBCINobleEmitterStateChange: obciNobleEmitterStateChange,
1252 | OBCINobleStatePoweredOn: obciNobleStatePoweredOn,
1253 | getPeripheralLocalNames,
1254 | getPeripheralWithLocalName,
1255 | getVersionNumber,
1256 | isPeripheralGanglion,
1257 | commandSampleRateForCmdCyton,
1258 | commandSampleRateForCmdGanglion,
1259 | commandBoardModeForMode,
1260 | rawDataToSampleObjectDefault,
1261 | /** Protocols */
1262 | OBCIProtocolBLE: obciProtocolBLE,
1263 | OBCIProtocolSerial: obciProtocolSerial,
1264 | OBCIProtocolWifi: obciProtocolWifi,
1265 | /** Register Query for Cyton */
1266 | OBCIRegisterQueryAccelerometerFirmwareV1: obciRegisterQueryAccelerometerFirmwareV1,
1267 | OBCIRegisterQueryAccelerometerFirmwareV3: obciRegisterQueryAccelerometerFirmwareV3,
1268 | OBCIRegisterQueryCyton: obciRegisterQueryCyton,
1269 | OBCIRegisterQueryCytonDaisy: obciRegisterQueryCytonDaisy,
1270 | OBCIRegisterQueryNameMISC1: obciRegisterQueryNameMISC1,
1271 | OBCIRegisterQueryNameBIASSENSP: obciRegisterQueryNameBIASSENSP,
1272 | OBCIRegisterQueryNameCHnSET: obciRegisterQueryNameCHnSET,
1273 | OBCIRegisterQuerySizeCytonFirmwareV1: obciRegisterQuerySizeCytonFirmwareV1,
1274 | OBCIRegisterQuerySizeCytonDaisyFirmwareV1: obciRegisterQuerySizeCytonDaisyFirmwareV1,
1275 | OBCIRegisterQuerySizeCytonFirmwareV3: obciRegisterQuerySizeCytonFirmwareV3,
1276 | OBCIRegisterQuerySizeCytonDaisyFirmwareV3: obciRegisterQuerySizeCytonDaisyFirmwareV3
1277 | };
1278 |
1279 | /**
1280 | * @description To add a usability abstraction layer above channel setting commands. Due to the
1281 | * extensive and highly specific nature of the channel setting command chain, this
1282 | * will take several different human readable inputs and merge to one array filled
1283 | * with the correct commands, prime for sending directly to the write command.
1284 | * @param channelNumber - Number (1-16)
1285 | * @param powerDown - Bool (true -> OFF, false -> ON (default))
1286 | * turns the channel on or off
1287 | * @param gain - Number (1,2,4,6,8,12,24(default))
1288 | * sets the gain for the channel
1289 | * @param inputType - String (normal,shorted,biasMethod,mvdd,temp,testsig,biasDrp,biasDrn)
1290 | * selects the ADC channel input source
1291 | * @param bias - Bool (true -> Include in bias (default), false -> remove from bias)
1292 | * selects to include the channel input in bias generation
1293 | * @param srb2 - Bool (true -> Connect this input to SRB2 (default),
1294 | * false -> Disconnect this input from SRB2)
1295 | * Select to connect (true) this channel's P input to the SRB2 pin. This closes
1296 | * a switch between P input and SRB2 for the given channel, and allows the
1297 | * P input to also remain connected to the ADC.
1298 | * @param srb1 - Bool (true -> connect all N inputs to SRB1,
1299 | * false -> Disconnect all N inputs from SRB1 (default))
1300 | * Select to connect (true) all channels' N inputs to SRB1. This effects all pins,
1301 | * and disconnects all N inputs from the ADC.
1302 | * @returns {Promise} resolves {commandArray: array of commands to be sent,
1303 | newChannelSettingsObject: an updated channel settings object
1304 | to be stored in openBCIBoard.channelSettingsArray},
1305 | rejects on bad input or no board
1306 | */
1307 | function channelSetter (channelNumber, powerDown, gain, inputType, bias, srb2, srb1) {
1308 | // Used to store and assemble the commands
1309 | var cmdPowerDown,
1310 | cmdBias,
1311 | cmdSrb2,
1312 | cmdSrb1;
1313 |
1314 | return new Promise(function (resolve, reject) {
1315 | // Validate the input
1316 | if (!isNumber(channelNumber)) reject(Error("channelNumber must be of type 'number' "));
1317 | if (!isBoolean(powerDown)) reject(Error("powerDown must be of type 'boolean' "));
1318 | if (!isNumber(gain)) reject(Error("gain must be of type 'number' "));
1319 | if (!isString(inputType)) reject(Error("inputType must be of type 'string' "));
1320 | if (!isBoolean(bias)) reject(Error("bias must be of type 'boolean' "));
1321 | if (!isBoolean(srb2)) reject(Error("srb1 must be of type 'boolean' "));
1322 | if (!isBoolean(srb1)) reject(Error("srb2 must be of type 'boolean' "));
1323 |
1324 | // Set Channel Number
1325 | var p1 = commandChannelForCmd(channelNumber)
1326 | .catch(err => reject(err));
1327 |
1328 | // Set POWER_DOWN
1329 | cmdPowerDown = powerDown ? obciChannelCmdPowerOff : obciChannelCmdPowerOn;
1330 |
1331 | // Set Gain
1332 | var p2 = commandForGain(gain)
1333 | .catch(err => reject(err));
1334 |
1335 | // Set ADC string
1336 | var p3 = commandForADCString(inputType)
1337 | .catch(err => reject(err));
1338 |
1339 | // Set BIAS
1340 | cmdBias = bias ? obciChannelCmdBiasInclude : obciChannelCmdBiasRemove;
1341 |
1342 | // Set SRB2
1343 | cmdSrb2 = srb2 ? obciChannelCmdSRB2Connect : obciChannelCmdSRB2Diconnect;
1344 |
1345 | // Set SRB1
1346 | cmdSrb1 = srb1 ? obciChannelCmdSRB1Connect : obciChannelCmdSRB1Diconnect;
1347 |
1348 | var newChannelSettingsObject = {
1349 | channelNumber: channelNumber,
1350 | powerDown: powerDown,
1351 | gain: gain,
1352 | inputType: inputType,
1353 | bias: bias,
1354 | srb2: srb2,
1355 | srb1: srb1
1356 | };
1357 |
1358 | Promise.all([p1, p2, p3]).then(function (values) {
1359 | var outputArray = [
1360 | obciChannelCmdSet,
1361 | values[0],
1362 | cmdPowerDown,
1363 | values[1],
1364 | values[2],
1365 | cmdBias,
1366 | cmdSrb2,
1367 | cmdSrb1,
1368 | obciChannelCmdLatch
1369 | ];
1370 | resolve({commandArray: outputArray, newChannelSettingsObject: newChannelSettingsObject});
1371 | });
1372 | });
1373 | }
1374 |
1375 | /**
1376 | * @description To build the array of commands to send to the board to measure impedance
1377 | * @param channelNumber
1378 | * @param pInputApplied - Bool (true -> Test Signal Applied, false -> Test Signal Not Applied (default))
1379 | * applies the test signal to the P input
1380 | * @param nInputApplied - Bool (true -> Test Signal Applied, false -> Test Signal Not Applied (default))
1381 | * applies the test signal to the N input
1382 | * @returns {Promise} - fulfilled will contain an array of comamnds
1383 | */
1384 | function impedanceSetter (channelNumber, pInputApplied, nInputApplied) {
1385 | var cmdNInputApplied,
1386 | cmdPInputApplied;
1387 | return new Promise((resolve, reject) => {
1388 | // validate inputs
1389 | if (!isNumber(channelNumber)) reject(Error("channelNumber must be of type 'number' "));
1390 | if (!isBoolean(pInputApplied)) reject(Error("pInputApplied must be of type 'boolean' "));
1391 | if (!isBoolean(nInputApplied)) reject(Error("nInputApplied must be of type 'boolean' "));
1392 |
1393 | // Set pInputApplied
1394 | cmdPInputApplied = pInputApplied ? obciChannelImpedanceTestSignalApplied : obciChannelImpedanceTestSignalAppliedNot;
1395 |
1396 | // Set nInputApplied
1397 | cmdNInputApplied = nInputApplied ? obciChannelImpedanceTestSignalApplied : obciChannelImpedanceTestSignalAppliedNot;
1398 |
1399 | // Set Channel Number
1400 | commandChannelForCmd(channelNumber).then(command => {
1401 | var outputArray = [
1402 | obciChannelImpedanceSet,
1403 | command,
1404 | cmdPInputApplied,
1405 | cmdNInputApplied,
1406 | obciChannelImpedanceLatch
1407 | ];
1408 | // console.log(outputArray)
1409 | resolve(outputArray);
1410 | }).catch(err => reject(err));
1411 | });
1412 | }
1413 |
1414 | /**
1415 | * @description To build the array of commands to send to the board to set the sample rate
1416 | * @param boardType {String} - The type of board, either cyton or ganglion. Default is Cyton
1417 | * @param sampleRate {Number} - The sample rate you want to set to. Please see docs for possible sample rates.
1418 | * @returns {Promise} - fulfilled will contain an array of commands
1419 | */
1420 | function sampleRateSetter (boardType, sampleRate) {
1421 | return new Promise((resolve, reject) => {
1422 | // validate inputs
1423 | if (!isString(boardType)) return reject(Error("board type must be of type 'string' "));
1424 |
1425 | if (!isNumber(sampleRate)) return reject(Error("sampleRate must be of type 'number' "));
1426 |
1427 | sampleRate = Math.floor(sampleRate);
1428 |
1429 | let func;
1430 | if (boardType === obciBoardCyton || boardType === obciBoardDaisy) {
1431 | func = commandSampleRateForCmdCyton;
1432 | } else if (boardType === obciBoardGanglion) {
1433 | func = commandSampleRateForCmdGanglion;
1434 | } else {
1435 | return reject(Error(`boardType must be either ${obciBoardCyton} or ${obciBoardGanglion}`));
1436 | }
1437 |
1438 | // Set Channel Number
1439 | func(sampleRate).then(command => {
1440 | var outputArray = [
1441 | obciSampleRateSet,
1442 | command
1443 | ];
1444 | // console.log(outputArray)
1445 | resolve(outputArray);
1446 | }).catch(err => reject(err));
1447 | });
1448 | }
1449 |
1450 | /**
1451 | * @description To build the array of commands to send to the board t
1452 | * @param boardMode {String} - The type of board mode:
1453 | * `default`: Board will use Accel
1454 | * `
1455 | * @returns {Promise} - fulfilled will contain an array of commands
1456 | */
1457 | function boardModeSetter (boardMode) {
1458 | return new Promise((resolve, reject) => {
1459 | // validate inputs
1460 | if (!isString(boardMode)) return reject(Error("board mode must be of type 'string' "));
1461 | // Set Channel Number
1462 | commandBoardModeForMode(boardMode).then(command => {
1463 | var outputArray = [
1464 | obciBoardModeSet,
1465 | command
1466 | ];
1467 | // console.log(outputArray)
1468 | resolve(outputArray);
1469 | }).catch(err => reject(err));
1470 | });
1471 | }
1472 |
1473 | function isNumber (input) {
1474 | return (typeof input === 'number');
1475 | }
1476 | function isBoolean (input) {
1477 | return (typeof input === 'boolean');
1478 | }
1479 | function isString (input) {
1480 | return (typeof input === 'string');
1481 | }
1482 | function isUndefined (input) {
1483 | return (typeof input === 'undefined');
1484 | }
1485 | function isNull (input) {
1486 | return input === null;
1487 | }
1488 |
1489 | function commandForADCString (adcString) {
1490 | return new Promise(function (resolve, reject) {
1491 | switch (adcString) {
1492 | case obciStringADCNormal:
1493 | resolve(obciChannelCmdADCNormal);
1494 | break;
1495 | case obciStringADCShorted:
1496 | resolve(obciChannelCmdADCShorted);
1497 | break;
1498 | case obciStringADCBiasMethod:
1499 | resolve(obciChannelCmdADCBiasMethod);
1500 | break;
1501 | case obciStringADCMvdd:
1502 | resolve(obciChannelCmdADCMVDD);
1503 | break;
1504 | case obciStringADCTemp:
1505 | resolve(obciChannelCmdADCTemp);
1506 | break;
1507 | case obciStringADCTestSig:
1508 | resolve(obciChannelCmdADCTestSig);
1509 | break;
1510 | case obciStringADCBiasDrp:
1511 | resolve(obciChannelCmdADCBiasDRP);
1512 | break;
1513 | case obciStringADCBiasDrn:
1514 | resolve(obciChannelCmdADCBiasDRN);
1515 | break;
1516 | default:
1517 | reject(Error('Invalid ADC string'));
1518 | break;
1519 | }
1520 | });
1521 | }
1522 |
1523 | /**
1524 | * Returns the input type for the given command
1525 | * @param cmd {Number} The command
1526 | * @returns {String}
1527 | */
1528 | function inputTypeForCommand (cmd) {
1529 | switch (String(cmd)) {
1530 | case obciChannelCmdADCNormal:
1531 | return obciStringADCNormal;
1532 | case obciChannelCmdADCShorted:
1533 | return obciStringADCShorted;
1534 | case obciChannelCmdADCBiasMethod:
1535 | return obciStringADCBiasMethod;
1536 | case obciChannelCmdADCMVDD:
1537 | return obciStringADCMvdd;
1538 | case obciChannelCmdADCTemp:
1539 | return obciStringADCTemp;
1540 | case obciChannelCmdADCTestSig:
1541 | return obciStringADCTestSig;
1542 | case obciChannelCmdADCBiasDRP:
1543 | return obciStringADCBiasDrp;
1544 | case obciChannelCmdADCBiasDRN:
1545 | return obciStringADCBiasDrn;
1546 | default:
1547 | throw new Error('Invalid input type, must be less than 8');
1548 | }
1549 | }
1550 |
1551 | function commandForGain (gainSetting) {
1552 | return new Promise(function (resolve, reject) {
1553 | switch (gainSetting) {
1554 | case 1:
1555 | resolve(obciChannelCmdGain1);
1556 | break;
1557 | case 2:
1558 | resolve(obciChannelCmdGain2);
1559 | break;
1560 | case 4:
1561 | resolve(obciChannelCmdGain4);
1562 | break;
1563 | case 6:
1564 | resolve(obciChannelCmdGain6);
1565 | break;
1566 | case 8:
1567 | resolve(obciChannelCmdGain8);
1568 | break;
1569 | case 12:
1570 | resolve(obciChannelCmdGain12);
1571 | break;
1572 | case 24:
1573 | resolve(obciChannelCmdGain24);
1574 | break;
1575 | default:
1576 | reject(Error('Invalid gain setting of ' + gainSetting + ' gain must be (1,2,4,6,8,12,24)'));
1577 | break;
1578 | }
1579 | });
1580 | }
1581 |
1582 | /**
1583 | * Get the gain
1584 | * @param cmd {Number}
1585 | * @returns {Number}
1586 | */
1587 | function gainForCommand (cmd) {
1588 | switch (String(cmd)) {
1589 | case obciChannelCmdGain1:
1590 | return 1;
1591 | case obciChannelCmdGain2:
1592 | return 2;
1593 | case obciChannelCmdGain4:
1594 | return 4;
1595 | case obciChannelCmdGain6:
1596 | return 6;
1597 | case obciChannelCmdGain8:
1598 | return 8;
1599 | case obciChannelCmdGain12:
1600 | return 12;
1601 | case obciChannelCmdGain24:
1602 | return 24;
1603 | default:
1604 | throw new Error(`Invalid gain setting of ${cmd} gain must be (0,1,2,3,4,5,6)`);
1605 | }
1606 | }
1607 |
1608 | function commandChannelForCmd (channelNumber) {
1609 | return new Promise(function (resolve, reject) {
1610 | switch (channelNumber) {
1611 | case 1:
1612 | resolve(obciChannelCmdChannel1);
1613 | break;
1614 | case 2:
1615 | resolve(obciChannelCmdChannel2);
1616 | break;
1617 | case 3:
1618 | resolve(obciChannelCmdChannel3);
1619 | break;
1620 | case 4:
1621 | resolve(obciChannelCmdChannel4);
1622 | break;
1623 | case 5:
1624 | resolve(obciChannelCmdChannel5);
1625 | break;
1626 | case 6:
1627 | resolve(obciChannelCmdChannel6);
1628 | break;
1629 | case 7:
1630 | resolve(obciChannelCmdChannel7);
1631 | break;
1632 | case 8:
1633 | resolve(obciChannelCmdChannel8);
1634 | break;
1635 | case 9:
1636 | resolve(obciChannelCmdChannel9);
1637 | break;
1638 | case 10:
1639 | resolve(obciChannelCmdChannel10);
1640 | break;
1641 | case 11:
1642 | resolve(obciChannelCmdChannel11);
1643 | break;
1644 | case 12:
1645 | resolve(obciChannelCmdChannel12);
1646 | break;
1647 | case 13:
1648 | resolve(obciChannelCmdChannel13);
1649 | break;
1650 | case 14:
1651 | resolve(obciChannelCmdChannel14);
1652 | break;
1653 | case 15:
1654 | resolve(obciChannelCmdChannel15);
1655 | break;
1656 | case 16:
1657 | resolve(obciChannelCmdChannel16);
1658 | break;
1659 | default:
1660 | reject(Error('Invalid channel number'));
1661 | break;
1662 | }
1663 | });
1664 | }
1665 |
1666 | /**
1667 | * @typedef {Object} ChannelSettingsObject - See page 50 of the ads1299.pdf
1668 | * @property {Number} channelNumber - The channel number of this object
1669 | * @property {Boolean} powerDown - Power-down: - This boolean determines the channel power mode for the
1670 | * corresponding channel. `false` for normal operation, channel is on, and `true` for channel
1671 | * power-down, channel is off. (Default is `false`)
1672 | * @property {Number} gain - PGA gain: This number determines the PGA gain setting. Can be either 1, 2, 4, 6, 8, 12, 24
1673 | * (Default is 24)
1674 | * @property {String} inputType - Channel input: This string is used to determine the channel input selection.
1675 | * Can be:
1676 | * 'normal' - Normal electrode input (Default)
1677 | * 'shorted' - Input shorted (for offset or noise measurements)
1678 | * 'biasMethod' - Used in conjunction with BIAS_MEAS bit for BIAS measurements.
1679 | * 'mvdd' - MVDD for supply measurement
1680 | * 'temp' - Temperature sensor
1681 | * 'testsig' - Test signal
1682 | * 'biasDrp' - BIAS_DRP (positive electrode is the driver)
1683 | * 'biasDrn' - BIAS_DRN (negative electrode is the driver)
1684 | * @property {Boolean} bias - BIAS: Is the channel included in the bias? If `true` or yes, this channel has both P
1685 | * and N channels connected to the bias. (Default is `true`)
1686 | * @property {Boolean} srb2 - SRB2 connection: This boolean determines the SRB2 connection for the corresponding
1687 | * channel. `false` for open, not connected to channel, and `true` for closed, connected to the
1688 | * channel. (Default is `true`)
1689 | * @property {Boolean} srb1 - Stimulus, reference, and bias 1: This boolean connects the SRB2 to all 4, 6, or 8
1690 | * channels inverting inputs. `false` when switches open, disconnected, and `true` when switches
1691 | * closed, or connected. (Default is `false`)
1692 | */
1693 |
1694 | /**
1695 | * Get an object of default board settings.
1696 | * @param channelNumber
1697 | * @returns {ChannelSettingsObject}
1698 | */
1699 | function channelSettingsObjectDefault (channelNumber) {
1700 | return {
1701 | channelNumber: channelNumber,
1702 | powerDown: false,
1703 | gain: 24,
1704 | inputType: obciStringADCNormal,
1705 | bias: true,
1706 | srb2: true,
1707 | srb1: false
1708 | };
1709 | }
1710 |
1711 | /**
1712 | * @description RawDataToSample default object creation
1713 | * @param numChannels {Number} - The number of channels
1714 | * @returns {RawDataToSample} - A new object
1715 | */
1716 | function rawDataToSampleObjectDefault (numChannels) {
1717 | if (numChannels === undefined) numChannels = obciNumberOfChannelsDefault;
1718 | return {
1719 | accelArray: [0, 0, 0],
1720 | channelSettings: constantsModule.channelSettingsArrayInit(numChannels),
1721 | decompressedSamples: decompressedSamplesInit(numChannels),
1722 | lastSampleNumber: 0,
1723 | rawDataPacket: Buffer.alloc(33),
1724 | rawDataPackets: [],
1725 | scale: true,
1726 | sendCounts: false,
1727 | timeOffset: 0,
1728 | verbose: false
1729 | };
1730 | }
1731 |
1732 | function decompressedSamplesInit (numChannels) {
1733 | let output = [];
1734 | for (let i = 0; i < 3; i++) {
1735 | output.push(new Array(numChannels));
1736 | }
1737 | return output;
1738 | }
1739 |
1740 | /**
1741 | * Get's the command for sample rate Cyton
1742 | * @param sampleRate {Number} - The desired sample rate
1743 | * @return {Promise}
1744 | */
1745 | function commandSampleRateForCmdCyton (sampleRate) {
1746 | return new Promise(function (resolve, reject) {
1747 | switch (sampleRate) {
1748 | case obciSampleRate16000:
1749 | resolve(obciSampleRateCmdCyton16000);
1750 | break;
1751 | case obciSampleRate8000:
1752 | resolve(obciSampleRateCmdCyton8000);
1753 | break;
1754 | case obciSampleRate4000:
1755 | resolve(obciSampleRateCmdCyton4000);
1756 | break;
1757 | case obciSampleRate2000:
1758 | resolve(obciSampleRateCmdCyton2000);
1759 | break;
1760 | case obciSampleRate1000:
1761 | resolve(obciSampleRateCmdCyton1000);
1762 | break;
1763 | case obciSampleRate500:
1764 | resolve(obciSampleRateCmdCyton500);
1765 | break;
1766 | case obciSampleRate250:
1767 | resolve(obciSampleRateCmdCyton250);
1768 | break;
1769 | default:
1770 | reject(Error('Invalid sample rate'));
1771 | break;
1772 | }
1773 | });
1774 | }
1775 |
1776 | /**
1777 | * Get's the command for sample rate Cyton
1778 | * @param sampleRate {Number} - The desired sample rate
1779 | * @return {Promise}
1780 | */
1781 | function commandSampleRateForCmdGanglion (sampleRate) {
1782 | return new Promise(function (resolve, reject) {
1783 | switch (sampleRate) {
1784 | case obciSampleRate25600:
1785 | resolve(obciSampleRateCmdGang25600);
1786 | break;
1787 | case obciSampleRate12800:
1788 | resolve(obciSampleRateCmdGang12800);
1789 | break;
1790 | case obciSampleRate6400:
1791 | resolve(obciSampleRateCmdGang6400);
1792 | break;
1793 | case obciSampleRate3200:
1794 | resolve(obciSampleRateCmdGang3200);
1795 | break;
1796 | case obciSampleRate1600:
1797 | resolve(obciSampleRateCmdGang1600);
1798 | break;
1799 | case obciSampleRate800:
1800 | resolve(obciSampleRateCmdGang800);
1801 | break;
1802 | case obciSampleRate400:
1803 | resolve(obciSampleRateCmdGang400);
1804 | break;
1805 | case obciSampleRate200:
1806 | resolve(obciSampleRateCmdGang200);
1807 | break;
1808 | default:
1809 | reject(Error('Invalid sample rate'));
1810 | break;
1811 | }
1812 | });
1813 | }
1814 |
1815 | /**
1816 | * Get's the command for sample rate Cyton
1817 | * @param boardMode {String} - The desired sample rate
1818 | * @return {Promise}
1819 | */
1820 | function commandBoardModeForMode (boardMode) {
1821 | return new Promise(function (resolve, reject) {
1822 | switch (boardMode) {
1823 | case obciBoardModeDefault:
1824 | resolve(obciBoardModeCmdDefault);
1825 | break;
1826 | case obciBoardModeDebug:
1827 | resolve(obciBoardModeCmdDebug);
1828 | break;
1829 | case obciBoardModeAnalog:
1830 | resolve(obciBoardModeCmdAnalog);
1831 | break;
1832 | case obciBoardModeDigital:
1833 | resolve(obciBoardModeCmdDigital);
1834 | break;
1835 | default:
1836 | reject(Error('Invalid sample rate'));
1837 | break;
1838 | }
1839 | });
1840 | }
1841 |
1842 | /**
1843 | * @description Get a list of local names from an array of peripherals
1844 | */
1845 | function getPeripheralLocalNames (pArray) {
1846 | return new Promise((resolve, reject) => {
1847 | var list = [];
1848 | pArray.forEach(perif => {
1849 | list.push(perif.advertisement.localName);
1850 | });
1851 | if (list.length > 0) {
1852 | return resolve(list);
1853 | } else {
1854 | return reject(Error(`No peripherals discovered with prefix equal to ${obciGanglionPrefix}`));
1855 | }
1856 | });
1857 | }
1858 |
1859 | /**
1860 | * @description Get a peripheral with a local name
1861 | * @param `pArray` {Array} - Array of peripherals
1862 | * @param `localName` {String} - The local name of the BLE device.
1863 | */
1864 | function getPeripheralWithLocalName (pArray, localName) {
1865 | return new Promise((resolve, reject) => {
1866 | if (typeof (pArray) !== 'object') return reject(Error(`pArray must be of type Object`));
1867 | pArray.forEach(perif => {
1868 | if (perif.advertisement.hasOwnProperty('localName')) {
1869 | if (perif.advertisement.localName === localName) {
1870 | return resolve(perif);
1871 | }
1872 | }
1873 | });
1874 | return reject(Error(`No peripheral found with localName: ${localName}`));
1875 | });
1876 | }
1877 |
1878 | /**
1879 | * @description This function is used to extract the major version from a github
1880 | * version string.
1881 | * @returns {Number} The major version number
1882 | */
1883 | function getVersionNumber (versionStr) {
1884 | return Number(versionStr[1]);
1885 | }
1886 |
1887 | /**
1888 | * @description Very safely checks to see if the noble peripheral is a
1889 | * ganglion by way of checking the local name property.
1890 | */
1891 | function isPeripheralGanglion (peripheral) {
1892 | if (peripheral) {
1893 | if (peripheral.hasOwnProperty('advertisement')) {
1894 | if (peripheral.advertisement !== null && peripheral.advertisement.hasOwnProperty('localName')) {
1895 | if (peripheral.advertisement.localName !== undefined && peripheral.advertisement.localName !== null) {
1896 | if (peripheral.advertisement.localName.indexOf(obciGanglionPrefix) > -1) {
1897 | return true;
1898 | }
1899 | }
1900 | }
1901 | }
1902 | }
1903 | return false;
1904 | }
1905 |
1906 | export default constantsModule;
1907 |
--------------------------------------------------------------------------------
/src/debug.js:
--------------------------------------------------------------------------------
1 |
2 | import { Buffer } from 'buffer/';
3 |
4 | /**
5 | * @description Output passed bytes on the console as a hexdump, if enabled
6 | * @param prefix - label to show to the left of bytes
7 | * @param data - bytes to output, a buffer or string
8 | * @private
9 | */
10 | export default function debugBytes (prefix, data) {
11 | if (typeof data === 'string') data = new Buffer(data);
12 |
13 | console.log('Debug bytes:');
14 |
15 | for (var j = 0; j < data.length;) {
16 | var hexPart = '';
17 | var ascPart = '';
18 | for (var end = Math.min(data.length, j + 16); j < end; ++j) {
19 | var byt = data[j];
20 |
21 | var hex = ('0' + byt.toString(16)).slice(-2);
22 | hexPart += (((j & 0xf) === 0x8) ? ' ' : ' '); // puts an extra space 8 bytes in
23 | hexPart += hex;
24 |
25 | var asc = (byt >= 0x20 && byt < 0x7f) ? String.fromCharCode(byt) : '.';
26 | ascPart += asc;
27 | }
28 |
29 | // pad to fixed width for alignment
30 | hexPart = (hexPart + ' ').substring(0, 3 * 17);
31 |
32 | console.log(prefix + ' ' + hexPart + '|' + ascPart + '|');
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import constants from './constants';
2 | import * as debug from './debug';
3 | import utilities from './utilities';
4 |
5 | export default {
6 | constants,
7 | debug,
8 | utilities
9 | };
10 |
--------------------------------------------------------------------------------
/test/bluebirdChecks.js:
--------------------------------------------------------------------------------
1 | var timingEventsAsPromises = require('./timingEventsAsPromises');
2 | exports.BluebirdPromise = require('bluebird');
3 | exports.PromiseIgnored = global.Promise;
4 |
5 | // Enable bluebird for all promise usage during tests only
6 | // Fails tests for issues bluebird finds
7 | // Exports a function to list all promises (getPendingPromises)
8 | // Exports a function to verify no promises pending within a timeout (noPendingPromises)
9 |
10 | exports.BluebirdPromise.config({
11 | // TODO: wForgottenReturn is disabled because timingEventsAsPromises triggers it; find a workaround
12 | warnings: { wForgottenReturn: false },
13 | longStackTraces: true,
14 | monitoring: true,
15 | cancellation: true
16 | });
17 |
18 | // nextTick conveniently not instrumented by timingEventsAsPromises
19 | exports.BluebirdPromise.setScheduler(process.nextTick);
20 |
21 | // unhandled rejections become test failures
22 | process.on('unhandledRejection', (reason, promise) => {
23 | if (!(reason instanceof Error)) {
24 | reason = new Error('unhandled promise rejection: ' + reason);
25 | } else {
26 | reason.message = 'unhandled promise rejection: ' + reason.message;
27 | }
28 | process.nextTick(() => { throw reason; });
29 | });
30 |
31 | // // warnings become test failures
32 | // process.on('warning', (warning) => {
33 | // var error = new Error(warning);
34 | // process.nextTick(() => { throw error; });
35 | // });
36 |
37 | // provide access to all currently pending promises
38 | var pendingPromises = {};
39 | var promiseId = 0;
40 | var nested = 0;
41 |
42 | function promiseCreationHandler (promise) {
43 | // promise created already resolved; ignore
44 | if (!promise.isPending()) return;
45 |
46 | // need to create another promise to get access to the extended stack trace
47 | // nested detects if we are inside our own dummy promise
48 | ++nested;
49 | if (nested === 1) {
50 | // not the dummy promise
51 | promise.___id = ++promiseId;
52 | // store promise details
53 | var error = new Error('Promise ' + promise.___id + ' is still pending');
54 | var entry = {
55 | promise: promise,
56 | id: promise.___id,
57 | error: error
58 | };
59 | pendingPromises[promise.___id] = entry;
60 | // extract stack trace by rejecting an error; bluebird fills in expanded stack
61 | exports.BluebirdPromise.reject(error).catch(error => {
62 | entry.error = error;
63 | entry.stack = error.stack;
64 | });
65 | } else {
66 | promise.___nested = nested;
67 | }
68 | --nested;
69 | }
70 | process.on('promiseCreated', promiseCreationHandler);
71 |
72 | function promiseDoneHandler (promise) {
73 | if (promise.___nested) return;
74 | delete pendingPromises[promise.___id];
75 | }
76 | process.on('promiseFulfilled', promiseDoneHandler);
77 | process.on('promiseRejected', promiseDoneHandler);
78 | process.on('promiseResolved', promiseDoneHandler);
79 | process.on('promiseCancelled', promiseDoneHandler);
80 |
81 | exports.getPendingPromises = function () {
82 | var ret = [];
83 | for (var promise in pendingPromises) {
84 | ret.push(pendingPromises[promise]);
85 | }
86 | return ret;
87 | };
88 |
89 | exports.noPendingPromises = function (milliseconds) {
90 | if (!milliseconds) milliseconds = 0;
91 |
92 | return new exports.PromiseIgnored((resolve, reject) => {
93 | function waited100 () {
94 | var promises = exports.getPendingPromises();
95 |
96 | if (promises.length === 0) {
97 | return resolve();
98 | }
99 |
100 | if (milliseconds > 0) {
101 | milliseconds -= 100;
102 | return timingEventsAsPromises.setTimeoutIgnored(waited100, 100);
103 | }
104 |
105 | // timed out, but promises remaining: cancel all
106 |
107 | console.log(promises.length + ' promises still pending');
108 |
109 | promises.forEach(promise => {
110 | promise.promise.cancel();
111 | });
112 |
113 | // report one
114 | reject(promises[0].error);
115 | }
116 |
117 | timingEventsAsPromises.setTimeoutIgnored(waited100, 0);
118 | });
119 | };
120 |
121 | // now instrument the Promise object itself to always use a simplified version of bluebird
122 | // bluebird is composed inside a bare-bones Promise object providing only the official calls
123 |
124 | global.Promise = function (handler) {
125 | this._promise = new exports.BluebirdPromise(handler);
126 | };
127 |
128 | // compose class methods
129 | ['all', 'race', 'reject', 'resolve'].forEach(classMethod => {
130 | global.Promise[classMethod] = function () {
131 | return exports.BluebirdPromise[classMethod].apply(exports.BluebirdPromise, [].slice.call(arguments));
132 | };
133 | Object.defineProperty(global.Promise[classMethod], 'name', { value: 'Promise.' + classMethod });
134 | });
135 |
136 | // compose object methods
137 | ['then', 'catch'].forEach(objectMethod => {
138 | global.Promise.prototype[objectMethod] = function () {
139 | return this._promise[objectMethod].apply(this._promise, [].slice.call(arguments));
140 | };
141 | Object.defineProperty(global.Promise.prototype[objectMethod], 'name', { value: 'Promise.' + objectMethod });
142 | });
143 |
--------------------------------------------------------------------------------
/test/openBCIConstants-test.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by ajk on 12/16/15.
3 | */
4 | 'use strict';
5 | /* global describe, it, afterEach */
6 | let bluebirdChecks = require('./bluebirdChecks');
7 | let assert = require('assert');
8 | let k = require('../dist/constants');
9 | let chai = require('chai');
10 | let expect = chai.expect;
11 | let should = chai.should(); // eslint-disable-line no-unused-vars
12 | let chaiAsPromised = require('chai-as-promised');
13 | chai.use(chaiAsPromised);
14 |
15 | let getListOfPeripheralsOfSize = (perifsToMake) => {
16 | perifsToMake = perifsToMake || 3;
17 |
18 | let output = [];
19 |
20 | for (let i = 0; i < perifsToMake; i++) {
21 | output.push({
22 | advertisement: {
23 | localName: makeLocalName(i),
24 | txPowerLevel: undefined,
25 | manufacturerData: undefined,
26 | serviceData: [],
27 | serviceUuids: []
28 | }
29 | });
30 | }
31 | return output;
32 | };
33 |
34 | let makeLocalName = (num) => {
35 | let localName = `${k.OBCIGanglionPrefix}-00`;
36 | if (num < 10) {
37 | localName = `${localName}0${num}`;
38 | } else {
39 | localName = `${localName}${num}`;
40 | }
41 | return localName;
42 | };
43 |
44 | describe('OpenBCIConstants', function () {
45 | afterEach(() => bluebirdChecks.noPendingPromises());
46 | describe('Turning Channels Off', function () {
47 | it('channel 1', function () {
48 | assert.equal('1', k.OBCIChannelOff1);
49 | });
50 | it('channel 2', function () {
51 | assert.equal('2', k.OBCIChannelOff2);
52 | });
53 | it('channel 3', function () {
54 | assert.equal('3', k.OBCIChannelOff3);
55 | });
56 | it('channel 4', function () {
57 | assert.equal('4', k.OBCIChannelOff4);
58 | });
59 | it('channel 5', function () {
60 | assert.equal('5', k.OBCIChannelOff5);
61 | });
62 | it('channel 6', function () {
63 | assert.equal('6', k.OBCIChannelOff6);
64 | });
65 | it('channel 7', function () {
66 | assert.equal('7', k.OBCIChannelOff7);
67 | });
68 | it('channel 8', function () {
69 | assert.equal('8', k.OBCIChannelOff8);
70 | });
71 | it('channel 9', function () {
72 | assert.equal('q', k.OBCIChannelOff9);
73 | });
74 | it('channel 10', function () {
75 | assert.equal('w', k.OBCIChannelOff10);
76 | });
77 | it('channel 11', function () {
78 | assert.equal('e', k.OBCIChannelOff11);
79 | });
80 | it('channel 12', function () {
81 | assert.equal('r', k.OBCIChannelOff12);
82 | });
83 | it('channel 13', function () {
84 | assert.equal('t', k.OBCIChannelOff13);
85 | });
86 | it('channel 14', function () {
87 | assert.equal('y', k.OBCIChannelOff14);
88 | });
89 | it('channel 15', function () {
90 | assert.equal('u', k.OBCIChannelOff15);
91 | });
92 | it('channel 16', function () {
93 | assert.equal('i', k.OBCIChannelOff16);
94 | });
95 | });
96 | describe('Turning Channels On', function () {
97 | it('channel 1', function () {
98 | assert.equal('!', k.OBCIChannelOn1);
99 | });
100 | it('channel 2', function () {
101 | assert.equal('@', k.OBCIChannelOn2);
102 | });
103 | it('channel 3', function () {
104 | assert.equal('#', k.OBCIChannelOn3);
105 | });
106 | it('channel 4', function () {
107 | assert.equal('$', k.OBCIChannelOn4);
108 | });
109 | it('channel 5', function () {
110 | assert.equal('%', k.OBCIChannelOn5);
111 | });
112 | it('channel 6', function () {
113 | assert.equal('^', k.OBCIChannelOn6);
114 | });
115 | it('channel 7', function () {
116 | assert.equal('&', k.OBCIChannelOn7);
117 | });
118 | it('channel 8', function () {
119 | assert.equal('*', k.OBCIChannelOn8);
120 | });
121 | it('channel 9', function () {
122 | assert.equal('Q', k.OBCIChannelOn9);
123 | });
124 | it('channel 10', function () {
125 | assert.equal('W', k.OBCIChannelOn10);
126 | });
127 | it('channel 11', function () {
128 | assert.equal('E', k.OBCIChannelOn11);
129 | });
130 | it('channel 12', function () {
131 | assert.equal('R', k.OBCIChannelOn12);
132 | });
133 | it('channel 13', function () {
134 | assert.equal('T', k.OBCIChannelOn13);
135 | });
136 | it('channel 14', function () {
137 | assert.equal('Y', k.OBCIChannelOn14);
138 | });
139 | it('channel 15', function () {
140 | assert.equal('U', k.OBCIChannelOn15);
141 | });
142 | it('channel 16', function () {
143 | assert.equal('I', k.OBCIChannelOn16);
144 | });
145 | });
146 | describe('Test Signal Control Commands', function () {
147 | it('Connect to DC', function () {
148 | assert.equal('p', k.OBCITestSignalConnectToDC);
149 | });
150 | it('Connect to Ground', function () {
151 | assert.equal('0', k.OBCITestSignalConnectToGround);
152 | });
153 | it('Connect to Pulse 1x Fast', function () {
154 | assert.equal('=', k.OBCITestSignalConnectToPulse1xFast);
155 | });
156 | it('Connect to Pulse 1x Slow', function () {
157 | assert.equal('-', k.OBCITestSignalConnectToPulse1xSlow);
158 | });
159 | it('Connect to Pulse 2x Fast', function () {
160 | assert.equal(']', k.OBCITestSignalConnectToPulse2xFast);
161 | });
162 | it('Connect to Pulse 2x Slow', function () {
163 | assert.equal('[', k.OBCITestSignalConnectToPulse2xSlow);
164 | });
165 | });
166 | describe('Channel Setting Commands', function () {
167 | describe('Channel Selection', function () {
168 | it('Channel 1', function () {
169 | assert.equal('1', k.OBCIChannelCmdChannel1);
170 | });
171 | it('Channel 2', function () {
172 | assert.equal('2', k.OBCIChannelCmdChannel2);
173 | });
174 | it('Channel 3', function () {
175 | assert.equal('3', k.OBCIChannelCmdChannel3);
176 | });
177 | it('Channel 4', function () {
178 | assert.equal('4', k.OBCIChannelCmdChannel4);
179 | });
180 | it('Channel 5', function () {
181 | assert.equal('5', k.OBCIChannelCmdChannel5);
182 | });
183 | it('Channel 6', function () {
184 | assert.equal('6', k.OBCIChannelCmdChannel6);
185 | });
186 | it('Channel 7', function () {
187 | assert.equal('7', k.OBCIChannelCmdChannel7);
188 | });
189 | it('Channel 8', function () {
190 | assert.equal('8', k.OBCIChannelCmdChannel8);
191 | });
192 | it('Channel 9', function () {
193 | assert.equal('Q', k.OBCIChannelCmdChannel9);
194 | });
195 | it('Channel 10', function () {
196 | assert.equal('W', k.OBCIChannelCmdChannel10);
197 | });
198 | it('Channel 11', function () {
199 | assert.equal('E', k.OBCIChannelCmdChannel11);
200 | });
201 | it('Channel 12', function () {
202 | assert.equal('R', k.OBCIChannelCmdChannel12);
203 | });
204 | it('Channel 13', function () {
205 | assert.equal('T', k.OBCIChannelCmdChannel13);
206 | });
207 | it('Channel 14', function () {
208 | assert.equal('Y', k.OBCIChannelCmdChannel14);
209 | });
210 | it('Channel 15', function () {
211 | assert.equal('U', k.OBCIChannelCmdChannel15);
212 | });
213 | it('Channel 16', function () {
214 | assert.equal('I', k.OBCIChannelCmdChannel16);
215 | });
216 | });
217 | describe('Power Down', function () {
218 | it('OFF', function () {
219 | assert.equal('1', k.OBCIChannelCmdPowerOff);
220 | });
221 | it('ON', function () {
222 | assert.equal('0', k.OBCIChannelCmdPowerOn);
223 | });
224 | });
225 | describe('Gain Setting', function () {
226 | it('1', function () {
227 | assert.equal('0', k.OBCIChannelCmdGain1);
228 | });
229 | it('2', function () {
230 | assert.equal('1', k.OBCIChannelCmdGain2);
231 | });
232 | it('4', function () {
233 | assert.equal('2', k.OBCIChannelCmdGain4);
234 | });
235 | it('6', function () {
236 | assert.equal('3', k.OBCIChannelCmdGain6);
237 | });
238 | it('8', function () {
239 | assert.equal('4', k.OBCIChannelCmdGain8);
240 | });
241 | it('12', function () {
242 | assert.equal('5', k.OBCIChannelCmdGain12);
243 | });
244 | it('24', function () {
245 | assert.equal('6', k.OBCIChannelCmdGain24);
246 | });
247 | });
248 | describe('#commandForGain', function () {
249 | it('gain of 1', function () {
250 | let expectation = '0';
251 | let result = k.commandForGain(1);
252 | return expect(result).to.eventually.equal(expectation);
253 | });
254 | it('gain of 2', function () {
255 | let expectation = '1';
256 | let result = k.commandForGain(2);
257 | return expect(result).to.eventually.equal(expectation);
258 | });
259 | it('gain of 4', function () {
260 | let expectation = '2';
261 | let result = k.commandForGain(4);
262 | return expect(result).to.eventually.equal(expectation);
263 | });
264 | it('gain of 6', function () {
265 | let expectation = '3';
266 | let result = k.commandForGain(6);
267 | return expect(result).to.eventually.equal(expectation);
268 | });
269 | it('gain of 8', function () {
270 | let expectation = '4';
271 | let result = k.commandForGain(8);
272 | return expect(result).to.eventually.equal(expectation);
273 | });
274 | it('gain of 12', function () {
275 | let expectation = '5';
276 | let result = k.commandForGain(12);
277 | return expect(result).to.eventually.equal(expectation);
278 | });
279 | it('gain of 24', function () {
280 | let expectation = '6';
281 | let result = k.commandForGain(24);
282 | return expect(result).to.eventually.equal(expectation);
283 | });
284 | it('Invalid command request', function () {
285 | let result = k.commandForGain('taco');
286 | return expect(result).to.be.rejected;
287 | });
288 | });
289 | describe('#gainForCommand', function () {
290 | it('gain of 1', function () {
291 | assert.equal(1, k.gainForCommand(k.OBCIChannelCmdGain1));
292 | });
293 | it('gain of 2', function () {
294 | assert.equal(2, k.gainForCommand(k.OBCIChannelCmdGain2));
295 | });
296 | it('gain of 4', function () {
297 | assert.equal(4, k.gainForCommand(k.OBCIChannelCmdGain4));
298 | });
299 | it('gain of 6', function () {
300 | assert.equal(6, k.gainForCommand(k.OBCIChannelCmdGain6));
301 | });
302 | it('gain of 8', function () {
303 | assert.equal(8, k.gainForCommand(k.OBCIChannelCmdGain8));
304 | });
305 | it('gain of 12', function () {
306 | assert.equal(12, k.gainForCommand(k.OBCIChannelCmdGain12));
307 | });
308 | it('gain of 24', function () {
309 | assert.equal(24, k.gainForCommand(k.OBCIChannelCmdGain24));
310 | });
311 | it('Invalid command request', function () {
312 | expect(k.gainForCommand.bind(k, '8')).to.throw(`Invalid gain setting of 8 gain must be (0,1,2,3,4,5,6)`);
313 | });
314 | });
315 | describe('#inputTypeForCommand', function () {
316 | it('Normal', function () {
317 | assert.equal(k.OBCIStringADCNormal, k.inputTypeForCommand(0));
318 | });
319 | it('Shorted', function () {
320 | assert.equal(k.OBCIStringADCShorted, k.inputTypeForCommand(1));
321 | });
322 | it('Bias Method', function () {
323 | assert.equal(k.OBCIStringADCBiasMethod, k.inputTypeForCommand(2));
324 | });
325 | it('MVDD', function () {
326 | assert.equal(k.OBCIStringADCMvdd, k.inputTypeForCommand(3));
327 | });
328 | it('Temp', function () {
329 | assert.equal(k.OBCIStringADCTemp, k.inputTypeForCommand(4));
330 | });
331 | it('Test Signal', function () {
332 | assert.equal(k.OBCIStringADCTestSig, k.inputTypeForCommand(5));
333 | });
334 | it('Bias Dr P', function () {
335 | assert.equal(k.OBCIStringADCBiasDrp, k.inputTypeForCommand(6));
336 | });
337 | it('Bias Dr N', function () {
338 | assert.equal(k.OBCIStringADCBiasDrn, k.inputTypeForCommand(7));
339 | });
340 | it('Invalid command request', function () {
341 | expect(k.inputTypeForCommand.bind(k, '8')).to.throw('Invalid input type, must be less than 8');
342 | });
343 | });
344 | describe('ADC Channel Input Soruce', function () {
345 | it('Normal', function () {
346 | assert.equal('0', k.OBCIChannelCmdADCNormal);
347 | });
348 | it('Shorted', function () {
349 | assert.equal('1', k.OBCIChannelCmdADCShorted);
350 | });
351 | it('Bias Method', function () {
352 | assert.equal('2', k.OBCIChannelCmdADCBiasMethod);
353 | });
354 | it('MVDD', function () {
355 | assert.equal('3', k.OBCIChannelCmdADCMVDD);
356 | });
357 | it('Temp', function () {
358 | assert.equal('4', k.OBCIChannelCmdADCTemp);
359 | });
360 | it('Test Signal', function () {
361 | assert.equal('5', k.OBCIChannelCmdADCTestSig);
362 | });
363 | it('Bias DRP', function () {
364 | assert.equal('6', k.OBCIChannelCmdADCBiasDRP);
365 | });
366 | it('Bias DRN', function () {
367 | assert.equal('7', k.OBCIChannelCmdADCBiasDRN);
368 | });
369 | });
370 | describe('Bias Set', function () {
371 | it('Include in BIAS', function () {
372 | assert.equal('1', k.OBCIChannelCmdBiasInclude);
373 | });
374 | it('Remove from BIAS', function () {
375 | assert.equal('0', k.OBCIChannelCmdBiasRemove);
376 | });
377 | });
378 | describe('SRB2 Set', function () {
379 | it('Disconnect this input from SRB2', function () {
380 | assert.equal('0', k.OBCIChannelCmdSRB2Diconnect);
381 | });
382 | it('Connect this input to the SRB2', function () {
383 | assert.equal('1', k.OBCIChannelCmdSRB2Connect);
384 | });
385 | });
386 | describe('SRB1 Set', function () {
387 | it('Disconnect this input from SRB1', function () {
388 | assert.equal('0', k.OBCIChannelCmdSRB1Diconnect);
389 | });
390 | it('Connect this input to the SRB1', function () {
391 | assert.equal('1', k.OBCIChannelCmdSRB1Connect);
392 | });
393 | });
394 | it('Command to access channel settings', function () {
395 | assert.equal('x', k.OBCIChannelCmdSet);
396 | });
397 | it('Command to latch', function () {
398 | assert.equal('X', k.OBCIChannelCmdLatch);
399 | });
400 | });
401 | describe('Default Channel Settings', function () {
402 | it('Set all channels to default', function () {
403 | assert.equal('d', k.OBCIChannelDefaultAllSet);
404 | });
405 | it('Get a report of the default settings card', function () {
406 | assert.equal('D', k.OBCIChannelDefaultAllGet);
407 | });
408 | });
409 | describe('LeadOff Impedance Commands', function () {
410 | it('Command to access impedance settings', function () {
411 | assert.equal('z', k.OBCIChannelImpedanceSet);
412 | });
413 | it('Command to latch', function () {
414 | assert.equal('Z', k.OBCIChannelImpedanceLatch);
415 | });
416 | it('Test signal not applied', function () {
417 | assert.equal('0', k.OBCIChannelImpedanceTestSignalAppliedNot);
418 | });
419 | it('Test signal applied', function () {
420 | assert.equal('1', k.OBCIChannelImpedanceTestSignalApplied);
421 | });
422 | });
423 | describe('Time Sync Stuff', function () {
424 | it('Can get proper array size', function () {
425 | assert.equal(10, k.OBCITimeSyncArraySize);
426 | });
427 | it('Get correct time sync with conf', function () {
428 | assert.equal(0.9, k.OBCITimeSyncMultiplierWithSyncConf);
429 | });
430 | it('Get correct time sync without conf', function () {
431 | assert.equal(0.75, k.OBCITimeSyncMultiplierWithoutSyncConf);
432 | });
433 | it('Get correct time sync transmission threshold', function () {
434 | assert.equal(10, k.OBCITimeSyncThresholdTransFailureMS);
435 | });
436 | });
437 | describe('SD card Commands', function () {
438 | it('logs for 1 hour', function () {
439 | assert.equal('G', k.OBCISDLogForHour1);
440 | });
441 | it('logs for 2 hours', function () {
442 | assert.equal('H', k.OBCISDLogForHour2);
443 | });
444 | it('logs for 4 hours', function () {
445 | assert.equal('J', k.OBCISDLogForHour4);
446 | });
447 | it('logs for 12 hours', function () {
448 | assert.equal('K', k.OBCISDLogForHour12);
449 | });
450 | it('logs for 24 hours', function () {
451 | assert.equal('L', k.OBCISDLogForHour24);
452 | });
453 | it('logs for 5 minutes', function () {
454 | assert.equal('A', k.OBCISDLogForMin5);
455 | });
456 | it('logs for 15 minutes', function () {
457 | assert.equal('S', k.OBCISDLogForMin15);
458 | });
459 | it('logs for 30 minutes', function () {
460 | assert.equal('F', k.OBCISDLogForMin30);
461 | });
462 | it('logs for 14 seconds', function () {
463 | assert.equal('a', k.OBCISDLogForSec14);
464 | });
465 | it('stop logging and close the SD file', function () {
466 | assert.equal('j', k.OBCISDLogStop);
467 | });
468 | });
469 | describe('SD card string Commands', function () {
470 | it('logs for 1 hour', function () {
471 | assert.equal('1hour', k.OBCIStringSDHour1);
472 | });
473 | it('logs for 2 hours', function () {
474 | assert.equal('2hour', k.OBCIStringSDHour2);
475 | });
476 | it('logs for 4 hours', function () {
477 | assert.equal('4hour', k.OBCIStringSDHour4);
478 | });
479 | it('logs for 12 hours', function () {
480 | assert.equal('12hour', k.OBCIStringSDHour12);
481 | });
482 | it('logs for 24 hours', function () {
483 | assert.equal('24hour', k.OBCIStringSDHour24);
484 | });
485 | it('logs for 5 minutes', function () {
486 | assert.equal('5min', k.OBCIStringSDMin5);
487 | });
488 | it('logs for 15 minutes', function () {
489 | assert.equal('15min', k.OBCIStringSDMin15);
490 | });
491 | it('logs for 30 minutes', function () {
492 | assert.equal('30min', k.OBCIStringSDMin30);
493 | });
494 | it('logs for 14 seconds', function () {
495 | assert.equal('14sec', k.OBCIStringSDSec14);
496 | });
497 | });
498 | describe('#sdSettingForString', function () {
499 | it('correct command for 1 hour', function () {
500 | let expectation = k.OBCISDLogForHour1;
501 | let result = k.sdSettingForString('1hour');
502 | return expect(result).to.eventually.equal(expectation);
503 | });
504 | it('correct command for 2 hour', function () {
505 | let expectation = k.OBCISDLogForHour2;
506 | let result = k.sdSettingForString('2hour');
507 | return expect(result).to.eventually.equal(expectation);
508 | });
509 | it('correct command for 4 hour', function () {
510 | let expectation = k.OBCISDLogForHour4;
511 | let result = k.sdSettingForString('4hour');
512 | return expect(result).to.eventually.equal(expectation);
513 | });
514 | it('correct command for 12 hour', function () {
515 | let expectation = k.OBCISDLogForHour12;
516 | let result = k.sdSettingForString('12hour');
517 | return expect(result).to.eventually.equal(expectation);
518 | });
519 | it('correct command for 24 hour', function () {
520 | let expectation = k.OBCISDLogForHour24;
521 | let result = k.sdSettingForString('24hour');
522 | return expect(result).to.eventually.equal(expectation);
523 | });
524 | it('correct command for 5 min', function () {
525 | let expectation = k.OBCISDLogForMin5;
526 | let result = k.sdSettingForString('5min');
527 | return expect(result).to.eventually.equal(expectation);
528 | });
529 | it('correct command for 15 min', function () {
530 | let expectation = k.OBCISDLogForMin15;
531 | let result = k.sdSettingForString('15min');
532 | return expect(result).to.eventually.equal(expectation);
533 | });
534 | it('correct command for 30 min', function () {
535 | let expectation = k.OBCISDLogForMin30;
536 | let result = k.sdSettingForString('30min');
537 | return expect(result).to.eventually.equal(expectation);
538 | });
539 | it('correct command for 14 seconds', function () {
540 | let expectation = k.OBCISDLogForSec14;
541 | let result = k.sdSettingForString('14sec');
542 | return expect(result).to.eventually.equal(expectation);
543 | });
544 | it('Invalid command request', function () {
545 | let result = k.sdSettingForString('taco');
546 | return expect(result).to.be.rejected;
547 | });
548 | });
549 | describe('Stream Data Commands', function () {
550 | it('starts', function () {
551 | assert.equal('b', k.OBCIStreamStart);
552 | });
553 | it('stops', function () {
554 | assert.equal('s', k.OBCIStreamStop);
555 | });
556 | });
557 | describe('Accel enable/disable commands', function () {
558 | it('starts', function () {
559 | assert.equal('n', k.OBCIAccelStart);
560 | });
561 | it('stops', function () {
562 | assert.equal('N', k.OBCIAccelStop);
563 | });
564 | });
565 | describe('Accel packet numbers', function () {
566 | it('X axis', function () {
567 | assert.equal(1, k.OBCIGanglionAccelAxisX);
568 | });
569 | it('Y axis', function () {
570 | assert.equal(2, k.OBCIGanglionAccelAxisY);
571 | });
572 | it('Z axis', function () {
573 | assert.equal(3, k.OBCIGanglionAccelAxisZ);
574 | });
575 | });
576 | describe('Miscellaneous', function () {
577 | it('queries register settings', function () {
578 | assert.equal('?', k.OBCIMiscQueryRegisterSettings);
579 | });
580 | it('softly resets the board', function () {
581 | assert.equal('v', k.OBCIMiscSoftReset);
582 | });
583 | });
584 | describe('Max channel number commands', function () {
585 | it('sets max of 8', function () {
586 | assert.equal('c', k.OBCIChannelMaxNumber8);
587 | });
588 | it('sets max of 16', function () {
589 | assert.equal('C', k.OBCIChannelMaxNumber16);
590 | });
591 | it('has correct return messages', function () {
592 | assert.equal('', k.OBCIChannelMaxNumber8NoDaisyToRemove);
593 | assert.equal('daisy removed', k.OBCIChannelMaxNumber8SuccessDaisyRemoved);
594 | assert.equal('16', k.OBCIChannelMaxNumber16DaisyAlreadyAttached);
595 | assert.equal('daisy attached16', k.OBCIChannelMaxNumber16DaisyAttached);
596 | assert.equal('no daisy to attach!8', k.OBCIChannelMaxNumber16NoDaisyAttached);
597 | });
598 | });
599 | describe('On board filters', function () {
600 | it('disable', function () {
601 | assert.equal('g', k.OBCIFilterDisable);
602 | });
603 | it('enable', function () {
604 | assert.equal('f', k.OBCIFilterEnable);
605 | });
606 | });
607 | describe('Stream packet types/codes', function () {
608 | it('Standard with Accel', function () {
609 | assert.equal(0, k.OBCIStreamPacketStandardAccel);
610 | });
611 | it('Standard with Raw Aux', function () {
612 | assert.equal(1, k.OBCIStreamPacketStandardRawAux);
613 | });
614 | it('User Defined Packet', function () {
615 | assert.equal(2, k.OBCIStreamPacketUserDefinedType);
616 | });
617 | it('Time Sync Set with accel', function () {
618 | assert.equal(3, k.OBCIStreamPacketAccelTimeSyncSet);
619 | });
620 | it('Time Synced with Accel', function () {
621 | assert.equal(4, k.OBCIStreamPacketAccelTimeSynced);
622 | });
623 | it('Time Sync set with Raw Aux', function () {
624 | assert.equal(5, k.OBCIStreamPacketRawAuxTimeSyncSet);
625 | });
626 | it('Time Synced with Raw Aux', function () {
627 | assert.equal(6, k.OBCIStreamPacketRawAuxTimeSynced);
628 | });
629 | it('Time Synced with Raw Aux', function () {
630 | assert.equal(7, k.OBCIStreamPacketImpedance);
631 | });
632 | });
633 | describe('Time synced with accel packet', function () {
634 | it('X axis', function () {
635 | assert.equal(7, k.OBCIAccelAxisX);
636 | });
637 | it('Y axis', function () {
638 | assert.equal(8, k.OBCIAccelAxisY);
639 | });
640 | it('Z axis', function () {
641 | assert.equal(9, k.OBCIAccelAxisZ);
642 | });
643 | });
644 | describe('Time sync useful numbers', function () {
645 | it('Time from the board is 4 bytes', function () {
646 | assert.equal(4, k.OBCIStreamPacketTimeByteSize);
647 | });
648 | });
649 | describe('should return the right command for each channel', function () {
650 | it('Channel 1', function () {
651 | let expectation = '1';
652 | let result = k.commandChannelForCmd(1);
653 | return expect(result).to.eventually.equal(expectation);
654 | });
655 | it('Channel 2', function () {
656 | let expectation = '2';
657 | let result = k.commandChannelForCmd(2);
658 | return expect(result).to.eventually.equal(expectation);
659 | });
660 | it('Channel 3', function () {
661 | let expectation = '3';
662 | let result = k.commandChannelForCmd(3);
663 | return expect(result).to.eventually.equal(expectation);
664 | });
665 | it('Channel 4', function () {
666 | let expectation = '4';
667 | let result = k.commandChannelForCmd(4);
668 | return expect(result).to.eventually.equal(expectation);
669 | });
670 | it('Channel 5', function () {
671 | let expectation = '5';
672 | let result = k.commandChannelForCmd(5);
673 | return expect(result).to.eventually.equal(expectation);
674 | });
675 | it('Channel 6', function () {
676 | let expectation = '6';
677 | let result = k.commandChannelForCmd(6);
678 | return expect(result).to.eventually.equal(expectation);
679 | });
680 | it('Channel 7', function () {
681 | let expectation = '7';
682 | let result = k.commandChannelForCmd(7);
683 | return expect(result).to.eventually.equal(expectation);
684 | });
685 | it('Channel 8', function () {
686 | let expectation = '8';
687 | let result = k.commandChannelForCmd(8);
688 | return expect(result).to.eventually.equal(expectation);
689 | });
690 | it('Channel 9', function () {
691 | let expectation = 'Q';
692 | let result = k.commandChannelForCmd(9);
693 | return expect(result).to.eventually.equal(expectation);
694 | });
695 | it('Channel 10', function () {
696 | let expectation = 'W';
697 | let result = k.commandChannelForCmd(10);
698 | return expect(result).to.eventually.equal(expectation);
699 | });
700 | it('Channel 11', function () {
701 | let expectation = 'E';
702 | let result = k.commandChannelForCmd(11);
703 | return expect(result).to.eventually.equal(expectation);
704 | });
705 | it('Channel 12', function () {
706 | let expectation = 'R';
707 | let result = k.commandChannelForCmd(12);
708 | return expect(result).to.eventually.equal(expectation);
709 | });
710 | it('Channel 13', function () {
711 | let expectation = 'T';
712 | let result = k.commandChannelForCmd(13);
713 | return expect(result).to.eventually.equal(expectation);
714 | });
715 | it('Channel 14', function () {
716 | let expectation = 'Y';
717 | let result = k.commandChannelForCmd(14);
718 | return expect(result).to.eventually.equal(expectation);
719 | });
720 | it('Channel 15', function () {
721 | let expectation = 'U';
722 | let result = k.commandChannelForCmd(15);
723 | return expect(result).to.eventually.equal(expectation);
724 | });
725 | it('Channel 16', function () {
726 | let expectation = 'I';
727 | let result = k.commandChannelForCmd(16);
728 | return expect(result).to.eventually.equal(expectation);
729 | });
730 | it('Invalid channel request', function () {
731 | let result = k.commandChannelForCmd(17);
732 | return expect(result).to.be.rejected;
733 | });
734 | });
735 | describe('should return correct channel off command for number', function () {
736 | it('Channel 1', function () {
737 | let expectation = '1';
738 | let result = k.commandChannelOff(1);
739 | return expect(result).to.eventually.equal(expectation);
740 | });
741 | it('Channel 2', function () {
742 | let expectation = '2';
743 | let result = k.commandChannelOff(2);
744 | return expect(result).to.eventually.equal(expectation);
745 | });
746 | it('Channel 3', function () {
747 | let expectation = '3';
748 | let result = k.commandChannelOff(3);
749 | return expect(result).to.eventually.equal(expectation);
750 | });
751 | it('Channel 4', function () {
752 | let expectation = '4';
753 | let result = k.commandChannelOff(4);
754 | return expect(result).to.eventually.equal(expectation);
755 | });
756 | it('Channel 5', function () {
757 | let expectation = '5';
758 | let result = k.commandChannelOff(5);
759 | return expect(result).to.eventually.equal(expectation);
760 | });
761 | it('Channel 6', function () {
762 | let expectation = '6';
763 | let result = k.commandChannelOff(6);
764 | return expect(result).to.eventually.equal(expectation);
765 | });
766 | it('Channel 7', function () {
767 | let expectation = '7';
768 | let result = k.commandChannelOff(7);
769 | return expect(result).to.eventually.equal(expectation);
770 | });
771 | it('Channel 8', function () {
772 | let expectation = '8';
773 | let result = k.commandChannelOff(8);
774 | return expect(result).to.eventually.equal(expectation);
775 | });
776 | it('Channel 9', function () {
777 | let expectation = 'q';
778 | let result = k.commandChannelOff(9);
779 | return expect(result).to.eventually.equal(expectation);
780 | });
781 | it('Channel 10', function () {
782 | let expectation = 'w';
783 | let result = k.commandChannelOff(10);
784 | return expect(result).to.eventually.equal(expectation);
785 | });
786 | it('Channel 11', function () {
787 | let expectation = 'e';
788 | let result = k.commandChannelOff(11);
789 | return expect(result).to.eventually.equal(expectation);
790 | });
791 | it('Channel 12', function () {
792 | let expectation = 'r';
793 | let result = k.commandChannelOff(12);
794 | return expect(result).to.eventually.equal(expectation);
795 | });
796 | it('Channel 13', function () {
797 | let expectation = 't';
798 | let result = k.commandChannelOff(13);
799 | return expect(result).to.eventually.equal(expectation);
800 | });
801 | it('Channel 14', function () {
802 | let expectation = 'y';
803 | let result = k.commandChannelOff(14);
804 | return expect(result).to.eventually.equal(expectation);
805 | });
806 | it('Channel 15', function () {
807 | let expectation = 'u';
808 | let result = k.commandChannelOff(15);
809 | return expect(result).to.eventually.equal(expectation);
810 | });
811 | it('Channel 16', function () {
812 | let expectation = 'i';
813 | let result = k.commandChannelOff(16);
814 | return expect(result).to.eventually.equal(expectation);
815 | });
816 | it('Invalid channel request', function () {
817 | let result = k.commandChannelOff(17);
818 | return expect(result).to.be.rejected;
819 | });
820 | });
821 | describe('should return the right command for each sample rate for cyton', function () {
822 | it('sample rate 16000', function () {
823 | let expectation = '0';
824 | let result = k.commandSampleRateForCmdCyton(16000);
825 | return expect(result).to.eventually.equal(expectation);
826 | });
827 | it('sample rate 8000', function () {
828 | let expectation = '1';
829 | let result = k.commandSampleRateForCmdCyton(8000);
830 | return expect(result).to.eventually.equal(expectation);
831 | });
832 | it('sample rate 4000', function () {
833 | let expectation = '2';
834 | let result = k.commandSampleRateForCmdCyton(4000);
835 | return expect(result).to.eventually.equal(expectation);
836 | });
837 | it('sample rate 2000', function () {
838 | let expectation = '3';
839 | let result = k.commandSampleRateForCmdCyton(2000);
840 | return expect(result).to.eventually.equal(expectation);
841 | });
842 | it('sample rate 1000', function () {
843 | let expectation = '4';
844 | let result = k.commandSampleRateForCmdCyton(1000);
845 | return expect(result).to.eventually.equal(expectation);
846 | });
847 | it('sample rate 500', function () {
848 | let expectation = '5';
849 | let result = k.commandSampleRateForCmdCyton(500);
850 | return expect(result).to.eventually.equal(expectation);
851 | });
852 | it('sample rate 250', function () {
853 | let expectation = '6';
854 | let result = k.commandSampleRateForCmdCyton(250);
855 | return expect(result).to.eventually.equal(expectation);
856 | });
857 | it('Invalid sample rate', function () {
858 | let result = k.commandSampleRateForCmdCyton(17);
859 | return expect(result).to.be.rejected;
860 | });
861 | it('Invalid sample rate type', function () {
862 | let result = k.commandSampleRateForCmdCyton('taco');
863 | return expect(result).to.be.rejected;
864 | });
865 | });
866 | describe('should return the right command for each sample rate for ganglion', function () {
867 | it('sample rate 25600', function () {
868 | let expectation = '0';
869 | let result = k.commandSampleRateForCmdGanglion(25600);
870 | return expect(result).to.eventually.equal(expectation);
871 | });
872 | it('sample rate 12800', function () {
873 | let expectation = '1';
874 | let result = k.commandSampleRateForCmdGanglion(12800);
875 | return expect(result).to.eventually.equal(expectation);
876 | });
877 | it('sample rate 6400', function () {
878 | let expectation = '2';
879 | let result = k.commandSampleRateForCmdGanglion(6400);
880 | return expect(result).to.eventually.equal(expectation);
881 | });
882 | it('sample rate 3200', function () {
883 | let expectation = '3';
884 | let result = k.commandSampleRateForCmdGanglion(3200);
885 | return expect(result).to.eventually.equal(expectation);
886 | });
887 | it('sample rate 1600', function () {
888 | let expectation = '4';
889 | let result = k.commandSampleRateForCmdGanglion(1600);
890 | return expect(result).to.eventually.equal(expectation);
891 | });
892 | it('sample rate 800', function () {
893 | let expectation = '5';
894 | let result = k.commandSampleRateForCmdGanglion(800);
895 | return expect(result).to.eventually.equal(expectation);
896 | });
897 | it('sample rate 400', function () {
898 | let expectation = '6';
899 | let result = k.commandSampleRateForCmdGanglion(400);
900 | return expect(result).to.eventually.equal(expectation);
901 | });
902 | it('sample rate 200', function () {
903 | let expectation = '7';
904 | let result = k.commandSampleRateForCmdGanglion(200);
905 | return expect(result).to.eventually.equal(expectation);
906 | });
907 | it('Invalid sample rate', function () {
908 | let result = k.commandSampleRateForCmdGanglion(17);
909 | return expect(result).to.be.rejected;
910 | });
911 | it('Invalid sample rate type', function () {
912 | let result = k.commandSampleRateForCmdGanglion('taco');
913 | return expect(result).to.be.rejected;
914 | });
915 | });
916 | describe('should return the right command for each board mode', function () {
917 | it('board mode default', function () {
918 | let expectation = '0';
919 | let result = k.commandBoardModeForMode('default');
920 | return expect(result).to.eventually.equal(expectation);
921 | });
922 | it('board mode debug', function () {
923 | let expectation = '1';
924 | let result = k.commandBoardModeForMode('debug');
925 | return expect(result).to.eventually.equal(expectation);
926 | });
927 | it('board mode 2', function () {
928 | let expectation = '2';
929 | let result = k.commandBoardModeForMode('analog');
930 | return expect(result).to.eventually.equal(expectation);
931 | });
932 | it('board mode 3', function () {
933 | let expectation = '3';
934 | let result = k.commandBoardModeForMode('digital');
935 | return expect(result).to.eventually.equal(expectation);
936 | });
937 | it('Invalid board mode', function () {
938 | let result = k.commandBoardModeForMode(10);
939 | return expect(result).to.be.rejected;
940 | });
941 | it('Invalid board mode', function () {
942 | let result = k.commandBoardModeForMode('taco');
943 | return expect(result).to.be.rejected;
944 | });
945 | });
946 | describe('should return correct channel on command for number', function () {
947 | it('Channel 1', function () {
948 | let expectation = '!';
949 | let result = k.commandChannelOn(1);
950 | return expect(result).to.eventually.equal(expectation);
951 | });
952 | it('Channel 2', function () {
953 | let expectation = '@';
954 | let result = k.commandChannelOn(2);
955 | return expect(result).to.eventually.equal(expectation);
956 | });
957 | it('Channel 3', function () {
958 | let expectation = '#';
959 | let result = k.commandChannelOn(3);
960 | return expect(result).to.eventually.equal(expectation);
961 | });
962 | it('Channel 4', function () {
963 | let expectation = '$';
964 | let result = k.commandChannelOn(4);
965 | return expect(result).to.eventually.equal(expectation);
966 | });
967 | it('Channel 5', function () {
968 | let expectation = '%';
969 | let result = k.commandChannelOn(5);
970 | return expect(result).to.eventually.equal(expectation);
971 | });
972 | it('Channel 6', function () {
973 | let expectation = '^';
974 | let result = k.commandChannelOn(6);
975 | return expect(result).to.eventually.equal(expectation);
976 | });
977 | it('Channel 7', function () {
978 | let expectation = '&';
979 | let result = k.commandChannelOn(7);
980 | return expect(result).to.eventually.equal(expectation);
981 | });
982 | it('Channel 8', function () {
983 | let expectation = '*';
984 | let result = k.commandChannelOn(8);
985 | return expect(result).to.eventually.equal(expectation);
986 | });
987 | it('Channel 9', function () {
988 | let expectation = 'Q';
989 | let result = k.commandChannelOn(9);
990 | return expect(result).to.eventually.equal(expectation);
991 | });
992 | it('Channel 10', function () {
993 | let expectation = 'W';
994 | let result = k.commandChannelOn(10);
995 | return expect(result).to.eventually.equal(expectation);
996 | });
997 | it('Channel 11', function () {
998 | let expectation = 'E';
999 | let result = k.commandChannelOn(11);
1000 | return expect(result).to.eventually.equal(expectation);
1001 | });
1002 | it('Channel 12', function () {
1003 | let expectation = 'R';
1004 | let result = k.commandChannelOn(12);
1005 | return expect(result).to.eventually.equal(expectation);
1006 | });
1007 | it('Channel 13', function () {
1008 | let expectation = 'T';
1009 | let result = k.commandChannelOn(13);
1010 | return expect(result).to.eventually.equal(expectation);
1011 | });
1012 | it('Channel 14', function () {
1013 | let expectation = 'Y';
1014 | let result = k.commandChannelOn(14);
1015 | return expect(result).to.eventually.equal(expectation);
1016 | });
1017 | it('Channel 15', function () {
1018 | let expectation = 'U';
1019 | let result = k.commandChannelOn(15);
1020 | return expect(result).to.eventually.equal(expectation);
1021 | });
1022 | it('Channel 16', function () {
1023 | let expectation = 'I';
1024 | let result = k.commandChannelOn(16);
1025 | return expect(result).to.eventually.equal(expectation);
1026 | });
1027 | it('Invalid channel request', function () {
1028 | let result = k.commandChannelOn(17);
1029 | return expect(result).to.be.rejected;
1030 | });
1031 | });
1032 | describe('Number of channels', function () {
1033 | it('Daisy', function () {
1034 | assert.equal(16, k.OBCINumberOfChannelsDaisy);
1035 | });
1036 | it('Default', function () {
1037 | assert.equal(8, k.OBCINumberOfChannelsDefault);
1038 | });
1039 | it('Cyton', function () {
1040 | assert.equal(8, k.OBCINumberOfChannelsCyton);
1041 | });
1042 | it('Cyton', function () {
1043 | assert.equal(2, k.OBCINumberOfChannelsCytonBLE);
1044 | });
1045 | it('Ganglion', function () {
1046 | assert.equal(4, k.OBCINumberOfChannelsGanglion);
1047 | });
1048 | });
1049 | describe('Possible Sample Rates', function () {
1050 | it('should be 125', function () {
1051 | assert.equal(125, k.OBCISampleRate125);
1052 | });
1053 | it('should be 250', function () {
1054 | assert.equal(250, k.OBCISampleRate250);
1055 | });
1056 | });
1057 | describe('Max sample number', function () {
1058 | it('should be 255', function () {
1059 | assert.equal(255, k.OBCISampleNumberMax);
1060 | });
1061 | });
1062 | describe('Radio Channel Limits', function () {
1063 | it('should get the right channel number max', function () {
1064 | expect(k.OBCIRadioChannelMax).to.be.equal(25);
1065 | });
1066 | it('should get the right channel number min', function () {
1067 | expect(k.OBCIRadioChannelMin).to.be.equal(1);
1068 | });
1069 | it('should get the right poll time max', function () {
1070 | expect(k.OBCIRadioPollTimeMax).to.be.equal(255);
1071 | });
1072 | it('should get the right poll time min', function () {
1073 | expect(k.OBCIRadioPollTimeMin).to.be.equal(0);
1074 | });
1075 | });
1076 | describe('Board Types', function () {
1077 | it('should get right name for chan daisy', function () {
1078 | expect(k.OBCIBoardDaisy).to.equal('daisy');
1079 | });
1080 | it('should get right name for chan cyton', function () {
1081 | expect(k.OBCIBoardCyton).to.equal('cyton');
1082 | });
1083 | it('should get right name for chan cyton BLE', function () {
1084 | expect(k.OBCIBoardCytonBLE).to.equal('cytonBLE');
1085 | });
1086 | it('should get right name for chan ganglion', function () {
1087 | expect(k.OBCIBoardGanglion).to.equal('ganglion');
1088 | });
1089 | it('should get right name for chan none', function () {
1090 | expect(k.OBCIBoardNone).to.equal('none');
1091 | });
1092 | });
1093 | describe('numberOfChannelsForBoardTypes', function () {
1094 | it('should get right num chan for daisy board', function () {
1095 | expect(k.numberOfChannelsForBoardType(k.OBCIBoardDaisy)).to.equal(16);
1096 | });
1097 | it('should get right num chan for cyton board', function () {
1098 | expect(k.numberOfChannelsForBoardType(k.OBCIBoardCyton)).to.equal(8);
1099 | });
1100 | it('should get right num chan for cyton BLE board', function () {
1101 | expect(k.numberOfChannelsForBoardType(k.OBCIBoardCytonBLE)).to.equal(2);
1102 | });
1103 | it('should get right num chan for ganglion', function () {
1104 | expect(k.numberOfChannelsForBoardType(k.OBCIBoardGanglion)).to.equal(4);
1105 | });
1106 | it('should get right num chan for none', function () {
1107 | expect(k.numberOfChannelsForBoardType(k.OBCIBoardNone)).to.equal(0);
1108 | });
1109 | });
1110 | describe('boardTypeForNumberOfChannels', function () {
1111 | it('should get daisy board right for num chan', function () {
1112 | expect(k.boardTypeForNumberOfChannels(16)).to.equal(k.OBCIBoardDaisy);
1113 | });
1114 | it('should get cyton board right for num chan', function () {
1115 | expect(k.boardTypeForNumberOfChannels(8)).to.equal(k.OBCIBoardCyton);
1116 | });
1117 | it('should get cyton BLE board right for num chan', function () {
1118 | expect(k.boardTypeForNumberOfChannels(2)).to.equal(k.OBCIBoardCytonBLE);
1119 | });
1120 | it('should get ganglion right for num chan', function () {
1121 | expect(k.boardTypeForNumberOfChannels(4)).to.equal(k.OBCIBoardGanglion);
1122 | });
1123 | it('should get none right for num chan', function () {
1124 | expect(k.boardTypeForNumberOfChannels(0)).to.equal(k.OBCIBoardNone);
1125 | });
1126 | });
1127 | describe('#getChannelSetter', function () {
1128 | // 'channel 1, power on, gain 24, inputType normal, bias include, srb2 connect, srb1 dissconnect'
1129 | describe('channel input selection works', function () {
1130 | // this.timeout(5000)
1131 | it('channel 2', function (done) {
1132 | k.getChannelSetter(2, false, 24, 'normal', true, true, false).then(function (val) {
1133 | val.commandArray[1].should.equal('2');
1134 | val.newChannelSettingsObject.channelNumber.should.equal(2);
1135 | val.newChannelSettingsObject.powerDown.should.equal(false);
1136 | val.newChannelSettingsObject.gain.should.equal(24);
1137 | val.newChannelSettingsObject.inputType.should.equal('normal');
1138 | val.newChannelSettingsObject.bias.should.equal(true);
1139 | val.newChannelSettingsObject.srb2.should.equal(true);
1140 | val.newChannelSettingsObject.srb1.should.equal(false);
1141 | done();
1142 | }).catch(function (err) {
1143 | done(err);
1144 | });
1145 | });
1146 | it('channel 5', function (done) {
1147 | k.getChannelSetter(5, false, 24, 'normal', true, true, false).then(function (val) {
1148 | val.commandArray[1].should.equal('5');
1149 | val.newChannelSettingsObject.channelNumber.should.equal(5);
1150 | val.newChannelSettingsObject.powerDown.should.equal(false);
1151 | val.newChannelSettingsObject.gain.should.equal(24);
1152 | val.newChannelSettingsObject.inputType.should.equal('normal');
1153 | val.newChannelSettingsObject.bias.should.equal(true);
1154 | val.newChannelSettingsObject.srb2.should.equal(true);
1155 | val.newChannelSettingsObject.srb1.should.equal(false);
1156 | done();
1157 | }).catch(function (err) {
1158 | done(err);
1159 | });
1160 | });
1161 | it('channel 9', function (done) {
1162 | k.getChannelSetter(9, false, 24, 'normal', true, true, false).then(function (val) {
1163 | val.commandArray[1].should.equal('Q');
1164 | val.newChannelSettingsObject.channelNumber.should.equal(9);
1165 | val.newChannelSettingsObject.powerDown.should.equal(false);
1166 | val.newChannelSettingsObject.gain.should.equal(24);
1167 | val.newChannelSettingsObject.inputType.should.equal('normal');
1168 | val.newChannelSettingsObject.bias.should.equal(true);
1169 | val.newChannelSettingsObject.srb2.should.equal(true);
1170 | val.newChannelSettingsObject.srb1.should.equal(false);
1171 | done();
1172 | }).catch(function (err) {
1173 | done(err);
1174 | });
1175 | });
1176 | it('channel 15', function (done) {
1177 | k.getChannelSetter(15, false, 24, 'normal', true, true, false).then(function (val) {
1178 | val.commandArray[1].should.equal('U');
1179 | val.newChannelSettingsObject.channelNumber.should.equal(15);
1180 | val.newChannelSettingsObject.powerDown.should.equal(false);
1181 | val.newChannelSettingsObject.gain.should.equal(24);
1182 | val.newChannelSettingsObject.inputType.should.equal('normal');
1183 | val.newChannelSettingsObject.bias.should.equal(true);
1184 | val.newChannelSettingsObject.srb2.should.equal(true);
1185 | val.newChannelSettingsObject.srb1.should.equal(false);
1186 | done();
1187 | }).catch(function (err) {
1188 | done(err);
1189 | });
1190 | });
1191 | it('Invalid channel selection', function (done) {
1192 | k.getChannelSetter(0, false, 24, 'normal', true, true, false).should.be.rejected.and.notify(done);
1193 | });
1194 | it('Invalid type', function (done) {
1195 | k.getChannelSetter('0', false, 24, 'normal', true, true, false).should.be.rejected.and.notify(done);
1196 | });
1197 | });
1198 | describe('power selection works', function () {
1199 | it('on', function (done) {
1200 | k.getChannelSetter(1, false, 24, 'normal', true, true, false).then(function (val) {
1201 | val.commandArray[2].should.equal('0');
1202 | val.newChannelSettingsObject.channelNumber.should.equal(1);
1203 | val.newChannelSettingsObject.powerDown.should.equal(false);
1204 | val.newChannelSettingsObject.gain.should.equal(24);
1205 | val.newChannelSettingsObject.inputType.should.equal('normal');
1206 | val.newChannelSettingsObject.bias.should.equal(true);
1207 | val.newChannelSettingsObject.srb2.should.equal(true);
1208 | val.newChannelSettingsObject.srb1.should.equal(false);
1209 | done();
1210 | }).catch(function (err) {
1211 | done(err);
1212 | });
1213 | });
1214 | it('off', function (done) {
1215 | k.getChannelSetter(1, true, 24, 'normal', true, true, false).then(function (val) {
1216 | val.commandArray[2].should.equal('1');
1217 | val.newChannelSettingsObject.channelNumber.should.equal(1);
1218 | val.newChannelSettingsObject.powerDown.should.equal(true);
1219 | val.newChannelSettingsObject.gain.should.equal(24);
1220 | val.newChannelSettingsObject.inputType.should.equal('normal');
1221 | val.newChannelSettingsObject.bias.should.equal(true);
1222 | val.newChannelSettingsObject.srb2.should.equal(true);
1223 | val.newChannelSettingsObject.srb1.should.equal(false);
1224 | done();
1225 | }).catch(function (err) {
1226 | done(err);
1227 | });
1228 | });
1229 | it('Invalid type', function (done) {
1230 | k.getChannelSetter(1, 'taco', 24, 'normal', true, true, false).should.be.rejected.and.notify(done);
1231 | });
1232 | });
1233 | describe('gain selection works', function () {
1234 | it('1x', function (done) {
1235 | k.getChannelSetter(1, false, 1, 'normal', true, true, false).then(function (val) {
1236 | val.commandArray[3].should.equal('0');
1237 | val.newChannelSettingsObject.channelNumber.should.equal(1);
1238 | val.newChannelSettingsObject.powerDown.should.equal(false);
1239 | val.newChannelSettingsObject.gain.should.equal(1);
1240 | val.newChannelSettingsObject.inputType.should.equal('normal');
1241 | val.newChannelSettingsObject.bias.should.equal(true);
1242 | val.newChannelSettingsObject.srb2.should.equal(true);
1243 | val.newChannelSettingsObject.srb1.should.equal(false);
1244 | done();
1245 | }).catch(function (err) {
1246 | done(err);
1247 | });
1248 | });
1249 | it('2x', function (done) {
1250 | k.getChannelSetter(1, false, 2, 'normal', true, true, false).then(function (val) {
1251 | val.commandArray[3].should.equal('1');
1252 | val.newChannelSettingsObject.channelNumber.should.equal(1);
1253 | val.newChannelSettingsObject.powerDown.should.equal(false);
1254 | val.newChannelSettingsObject.gain.should.equal(2);
1255 | val.newChannelSettingsObject.inputType.should.equal('normal');
1256 | val.newChannelSettingsObject.bias.should.equal(true);
1257 | val.newChannelSettingsObject.srb2.should.equal(true);
1258 | val.newChannelSettingsObject.srb1.should.equal(false);
1259 | done();
1260 | }).catch(function (err) {
1261 | done(err);
1262 | });
1263 | });
1264 | it('4x', function (done) {
1265 | k.getChannelSetter(1, false, 4, 'normal', true, true, false).then(function (val) {
1266 | val.commandArray[3].should.equal('2');
1267 | val.newChannelSettingsObject.channelNumber.should.equal(1);
1268 | val.newChannelSettingsObject.powerDown.should.equal(false);
1269 | val.newChannelSettingsObject.gain.should.equal(4);
1270 | val.newChannelSettingsObject.inputType.should.equal('normal');
1271 | val.newChannelSettingsObject.bias.should.equal(true);
1272 | val.newChannelSettingsObject.srb2.should.equal(true);
1273 | val.newChannelSettingsObject.srb1.should.equal(false);
1274 | done();
1275 | }).catch(function (err) {
1276 | done(err);
1277 | });
1278 | });
1279 | it('6x', function (done) {
1280 | k.getChannelSetter(1, false, 6, 'normal', true, true, false).then(function (val) {
1281 | val.commandArray[3].should.equal('3');
1282 | val.newChannelSettingsObject.channelNumber.should.equal(1);
1283 | val.newChannelSettingsObject.powerDown.should.equal(false);
1284 | val.newChannelSettingsObject.gain.should.equal(6);
1285 | val.newChannelSettingsObject.inputType.should.equal('normal');
1286 | val.newChannelSettingsObject.bias.should.equal(true);
1287 | val.newChannelSettingsObject.srb2.should.equal(true);
1288 | val.newChannelSettingsObject.srb1.should.equal(false);
1289 | done();
1290 | }).catch(function (err) {
1291 | done(err);
1292 | });
1293 | });
1294 | it('8x', function (done) {
1295 | k.getChannelSetter(1, false, 8, 'normal', true, true, false).then(function (val) {
1296 | val.commandArray[3].should.equal('4');
1297 | val.newChannelSettingsObject.channelNumber.should.equal(1);
1298 | val.newChannelSettingsObject.powerDown.should.equal(false);
1299 | val.newChannelSettingsObject.gain.should.equal(8);
1300 | val.newChannelSettingsObject.inputType.should.equal('normal');
1301 | val.newChannelSettingsObject.bias.should.equal(true);
1302 | val.newChannelSettingsObject.srb2.should.equal(true);
1303 | val.newChannelSettingsObject.srb1.should.equal(false);
1304 | done();
1305 | }).catch(function (err) {
1306 | done(err);
1307 | });
1308 | });
1309 | it('12x', function (done) {
1310 | k.getChannelSetter(1, false, 12, 'normal', true, true, false).then(function (val) {
1311 | val.commandArray[3].should.equal('5');
1312 | val.newChannelSettingsObject.channelNumber.should.equal(1);
1313 | val.newChannelSettingsObject.powerDown.should.equal(false);
1314 | val.newChannelSettingsObject.gain.should.equal(12);
1315 | val.newChannelSettingsObject.inputType.should.equal('normal');
1316 | val.newChannelSettingsObject.bias.should.equal(true);
1317 | val.newChannelSettingsObject.srb2.should.equal(true);
1318 | val.newChannelSettingsObject.srb1.should.equal(false);
1319 | done();
1320 | }).catch(function (err) {
1321 | done(err);
1322 | });
1323 | });
1324 | it('24x', function (done) {
1325 | k.getChannelSetter(1, false, 24, 'normal', true, true, false).then(function (val) {
1326 | val.commandArray[3].should.equal('6');
1327 | val.newChannelSettingsObject.channelNumber.should.equal(1);
1328 | val.newChannelSettingsObject.powerDown.should.equal(false);
1329 | val.newChannelSettingsObject.gain.should.equal(24);
1330 | val.newChannelSettingsObject.inputType.should.equal('normal');
1331 | val.newChannelSettingsObject.bias.should.equal(true);
1332 | val.newChannelSettingsObject.srb2.should.equal(true);
1333 | val.newChannelSettingsObject.srb1.should.equal(false);
1334 | done();
1335 | }).catch(function (err) {
1336 | done(err);
1337 | });
1338 | });
1339 | it('Invalid type', function (done) {
1340 | k.getChannelSetter(1, false, '24', 'normal', true, true, false).should.be.rejected.and.notify(done);
1341 | });
1342 | it('Invalid gain setting', function (done) {
1343 | k.getChannelSetter(1, false, 5, 'normal', true, true, false).should.be.rejected.and.notify(done);
1344 | });
1345 | });
1346 | describe('input type', function () {
1347 | it('normal', function (done) {
1348 | k.getChannelSetter(1, false, 24, 'normal', true, true, false).then(function (val) {
1349 | val.commandArray[4].should.equal('0');
1350 | val.newChannelSettingsObject.channelNumber.should.equal(1);
1351 | val.newChannelSettingsObject.powerDown.should.equal(false);
1352 | val.newChannelSettingsObject.gain.should.equal(24);
1353 | val.newChannelSettingsObject.inputType.should.equal('normal');
1354 | val.newChannelSettingsObject.bias.should.equal(true);
1355 | val.newChannelSettingsObject.srb2.should.equal(true);
1356 | val.newChannelSettingsObject.srb1.should.equal(false);
1357 | done();
1358 | }).catch(function (err) {
1359 | done(err);
1360 | });
1361 | });
1362 | it('shorted', function (done) {
1363 | k.getChannelSetter(1, false, 24, 'shorted', true, true, false).then(function (val) {
1364 | val.commandArray[4].should.equal('1');
1365 | val.newChannelSettingsObject.channelNumber.should.equal(1);
1366 | val.newChannelSettingsObject.powerDown.should.equal(false);
1367 | val.newChannelSettingsObject.gain.should.equal(24);
1368 | val.newChannelSettingsObject.inputType.should.equal('shorted');
1369 | val.newChannelSettingsObject.bias.should.equal(true);
1370 | val.newChannelSettingsObject.srb2.should.equal(true);
1371 | val.newChannelSettingsObject.srb1.should.equal(false);
1372 | done();
1373 | }).catch(function (err) {
1374 | done(err);
1375 | });
1376 | });
1377 | it('biasMethod', function (done) {
1378 | k.getChannelSetter(1, false, 24, 'biasMethod', true, true, false).then(function (val) {
1379 | val.commandArray[4].should.equal('2');
1380 | val.newChannelSettingsObject.channelNumber.should.equal(1);
1381 | val.newChannelSettingsObject.powerDown.should.equal(false);
1382 | val.newChannelSettingsObject.gain.should.equal(24);
1383 | val.newChannelSettingsObject.inputType.should.equal('biasMethod');
1384 | val.newChannelSettingsObject.bias.should.equal(true);
1385 | val.newChannelSettingsObject.srb2.should.equal(true);
1386 | val.newChannelSettingsObject.srb1.should.equal(false);
1387 | done();
1388 | }).catch(function (err) {
1389 | done(err);
1390 | });
1391 | });
1392 | it('mvdd', function (done) {
1393 | k.getChannelSetter(1, false, 24, 'mvdd', true, true, false).then(function (val) {
1394 | val.commandArray[4].should.equal('3');
1395 | val.newChannelSettingsObject.channelNumber.should.equal(1);
1396 | val.newChannelSettingsObject.powerDown.should.equal(false);
1397 | val.newChannelSettingsObject.gain.should.equal(24);
1398 | val.newChannelSettingsObject.inputType.should.equal('mvdd');
1399 | val.newChannelSettingsObject.bias.should.equal(true);
1400 | val.newChannelSettingsObject.srb2.should.equal(true);
1401 | val.newChannelSettingsObject.srb1.should.equal(false);
1402 | done();
1403 | }).catch(function (err) {
1404 | done(err);
1405 | });
1406 | });
1407 | it('temp', function (done) {
1408 | k.getChannelSetter(1, false, 24, 'temp', true, true, false).then(function (val) {
1409 | val.commandArray[4].should.equal('4');
1410 | val.newChannelSettingsObject.channelNumber.should.equal(1);
1411 | val.newChannelSettingsObject.powerDown.should.equal(false);
1412 | val.newChannelSettingsObject.gain.should.equal(24);
1413 | val.newChannelSettingsObject.inputType.should.equal('temp');
1414 | val.newChannelSettingsObject.bias.should.equal(true);
1415 | val.newChannelSettingsObject.srb2.should.equal(true);
1416 | val.newChannelSettingsObject.srb1.should.equal(false);
1417 | done();
1418 | }).catch(function (err) {
1419 | done(err);
1420 | });
1421 | });
1422 | it('testsig', function (done) {
1423 | k.getChannelSetter(1, false, 24, 'testSig', true, true, false).then(function (val) {
1424 | val.commandArray[4].should.equal('5');
1425 | val.newChannelSettingsObject.channelNumber.should.equal(1);
1426 | val.newChannelSettingsObject.powerDown.should.equal(false);
1427 | val.newChannelSettingsObject.gain.should.equal(24);
1428 | val.newChannelSettingsObject.inputType.should.equal('testSig');
1429 | val.newChannelSettingsObject.bias.should.equal(true);
1430 | val.newChannelSettingsObject.srb2.should.equal(true);
1431 | val.newChannelSettingsObject.srb1.should.equal(false);
1432 | done();
1433 | }).catch(function (err) {
1434 | done(err);
1435 | });
1436 | });
1437 | it('biasDrp', function (done) {
1438 | k.getChannelSetter(1, false, 24, 'biasDrp', true, true, false).then(function (val) {
1439 | val.commandArray[4].should.equal('6');
1440 | val.newChannelSettingsObject.channelNumber.should.equal(1);
1441 | val.newChannelSettingsObject.powerDown.should.equal(false);
1442 | val.newChannelSettingsObject.gain.should.equal(24);
1443 | val.newChannelSettingsObject.inputType.should.equal('biasDrp');
1444 | val.newChannelSettingsObject.bias.should.equal(true);
1445 | val.newChannelSettingsObject.srb2.should.equal(true);
1446 | val.newChannelSettingsObject.srb1.should.equal(false);
1447 | done();
1448 | }).catch(function (err) {
1449 | done(err);
1450 | });
1451 | });
1452 | it('biasDrn', function (done) {
1453 | k.getChannelSetter(1, false, 24, 'biasDrn', true, true, false).then(function (val) {
1454 | val.commandArray[4].should.equal('7');
1455 | val.newChannelSettingsObject.channelNumber.should.equal(1);
1456 | val.newChannelSettingsObject.powerDown.should.equal(false);
1457 | val.newChannelSettingsObject.gain.should.equal(24);
1458 | val.newChannelSettingsObject.inputType.should.equal('biasDrn');
1459 | val.newChannelSettingsObject.bias.should.equal(true);
1460 | val.newChannelSettingsObject.srb2.should.equal(true);
1461 | val.newChannelSettingsObject.srb1.should.equal(false);
1462 | done();
1463 | }).catch(function (err) {
1464 | done(err);
1465 | });
1466 | });
1467 | it('Invalid setting', function (done) {
1468 | k.getChannelSetter(1, false, 24, 'taco', true, true, false).should.be.rejected.and.notify(done);
1469 | });
1470 | it('Invalid type', function (done) {
1471 | k.getChannelSetter(1, false, 24, 1, true, true, false).should.be.rejected.and.notify(done);
1472 | });
1473 | });
1474 | describe('bias selection works', function () {
1475 | it('Include', function (done) {
1476 | k.getChannelSetter(1, false, 24, 'normal', true, true, false).then(function (val) {
1477 | val.commandArray[5].should.equal('1');
1478 | val.newChannelSettingsObject.channelNumber.should.equal(1);
1479 | val.newChannelSettingsObject.powerDown.should.equal(false);
1480 | val.newChannelSettingsObject.gain.should.equal(24);
1481 | val.newChannelSettingsObject.inputType.should.equal('normal');
1482 | val.newChannelSettingsObject.bias.should.equal(true);
1483 | val.newChannelSettingsObject.srb2.should.equal(true);
1484 | val.newChannelSettingsObject.srb1.should.equal(false);
1485 | done();
1486 | }).catch(function (err) {
1487 | done(err);
1488 | });
1489 | });
1490 | it('Remove', function (done) {
1491 | k.getChannelSetter(1, false, 24, 'normal', false, true, false).then(function (val) {
1492 | val.commandArray[5].should.equal('0');
1493 | val.newChannelSettingsObject.channelNumber.should.equal(1);
1494 | val.newChannelSettingsObject.powerDown.should.equal(false);
1495 | val.newChannelSettingsObject.gain.should.equal(24);
1496 | val.newChannelSettingsObject.inputType.should.equal('normal');
1497 | val.newChannelSettingsObject.bias.should.equal(false);
1498 | val.newChannelSettingsObject.srb2.should.equal(true);
1499 | val.newChannelSettingsObject.srb1.should.equal(false);
1500 | done();
1501 | }).catch(function (err) {
1502 | done(err);
1503 | });
1504 | });
1505 | it('Invalid type', function (done) {
1506 | k.getChannelSetter(1, false, 24, 'normal', 'taco', true, false).should.be.rejected.and.notify(done);
1507 | });
1508 | });
1509 | describe('SRB2 selection works', function () {
1510 | it('Connect', function (done) {
1511 | k.getChannelSetter(1, false, 24, 'normal', true, true, false).then(function (val) {
1512 | val.commandArray[6].should.equal('1');
1513 | val.newChannelSettingsObject.channelNumber.should.equal(1);
1514 | val.newChannelSettingsObject.powerDown.should.equal(false);
1515 | val.newChannelSettingsObject.gain.should.equal(24);
1516 | val.newChannelSettingsObject.inputType.should.equal('normal');
1517 | val.newChannelSettingsObject.bias.should.equal(true);
1518 | val.newChannelSettingsObject.srb2.should.equal(true);
1519 | val.newChannelSettingsObject.srb1.should.equal(false);
1520 | done();
1521 | }).catch(function (err) {
1522 | done(err);
1523 | });
1524 | });
1525 | it('Disconnect', function (done) {
1526 | k.getChannelSetter(1, false, 24, 'normal', true, false, false).then(function (val) {
1527 | val.commandArray[6].should.equal('0');
1528 | val.newChannelSettingsObject.channelNumber.should.equal(1);
1529 | val.newChannelSettingsObject.powerDown.should.equal(false);
1530 | val.newChannelSettingsObject.gain.should.equal(24);
1531 | val.newChannelSettingsObject.inputType.should.equal('normal');
1532 | val.newChannelSettingsObject.bias.should.equal(true);
1533 | val.newChannelSettingsObject.srb2.should.equal(false);
1534 | val.newChannelSettingsObject.srb1.should.equal(false);
1535 | done();
1536 | }).catch(function (err) {
1537 | done(err);
1538 | });
1539 | });
1540 | it('Invalid type', function (done) {
1541 | k.getChannelSetter(1, false, 24, 'normal', true, 'taco', false).should.be.rejected.and.notify(done);
1542 | });
1543 | });
1544 | describe('SRB1 selection works', function () {
1545 | it('Connect', function (done) {
1546 | k.getChannelSetter(1, false, 24, 'normal', true, true, true).then(function (val) {
1547 | val.commandArray[7].should.equal('1');
1548 | val.newChannelSettingsObject.channelNumber.should.equal(1);
1549 | val.newChannelSettingsObject.powerDown.should.equal(false);
1550 | val.newChannelSettingsObject.gain.should.equal(24);
1551 | val.newChannelSettingsObject.inputType.should.equal('normal');
1552 | val.newChannelSettingsObject.bias.should.equal(true);
1553 | val.newChannelSettingsObject.srb2.should.equal(true);
1554 | val.newChannelSettingsObject.srb1.should.equal(true);
1555 | done();
1556 | }).catch(function (err) {
1557 | done(err);
1558 | });
1559 | });
1560 | it('Disconnect', function (done) {
1561 | k.getChannelSetter(1, false, 24, 'normal', true, true, false).then(function (val) {
1562 | val.commandArray[7].should.equal('0');
1563 | val.newChannelSettingsObject.channelNumber.should.equal(1);
1564 | val.newChannelSettingsObject.powerDown.should.equal(false);
1565 | val.newChannelSettingsObject.gain.should.equal(24);
1566 | val.newChannelSettingsObject.inputType.should.equal('normal');
1567 | val.newChannelSettingsObject.bias.should.equal(true);
1568 | val.newChannelSettingsObject.srb2.should.equal(true);
1569 | val.newChannelSettingsObject.srb1.should.equal(false);
1570 | done();
1571 | }).catch(function (err) {
1572 | done(err);
1573 | });
1574 | });
1575 | it('Invalid type', function (done) {
1576 | k.getChannelSetter(1, false, 24, 'normal', true, true, 'taco').should.be.rejected.and.notify(done);
1577 | });
1578 | });
1579 | });
1580 | describe('#getTestSignalCommand', function () {
1581 | it('ground', function () {
1582 | let expectation = '0';
1583 | let result = k.getTestSignalCommand('ground');
1584 | return expect(result).to.eventually.equal(expectation);
1585 | });
1586 | it('dc', function () {
1587 | let expectation = 'p';
1588 | let result = k.getTestSignalCommand('dc');
1589 | return expect(result).to.eventually.equal(expectation);
1590 | });
1591 | it('Pulse 1x Fast', function () {
1592 | let expectation = '=';
1593 | let result = k.getTestSignalCommand('pulse1xFast');
1594 | return expect(result).to.eventually.equal(expectation);
1595 | });
1596 | it('Pulse 1x Slow', function () {
1597 | let expectation = '-';
1598 | let result = k.getTestSignalCommand('pulse1xSlow');
1599 | return expect(result).to.eventually.equal(expectation);
1600 | });
1601 | it('Pulse 2x Fast', function () {
1602 | let expectation = ']';
1603 | let result = k.getTestSignalCommand('pulse2xFast');
1604 | return expect(result).to.eventually.equal(expectation);
1605 | });
1606 | it('Pulse 2x Slow', function () {
1607 | let expectation = '[';
1608 | let result = k.getTestSignalCommand('pulse2xSlow');
1609 | return expect(result).to.eventually.equal(expectation);
1610 | });
1611 | it('none', function () {
1612 | let expectation = 'd';
1613 | let result = k.getTestSignalCommand('none');
1614 | return expect(result).to.eventually.equal(expectation);
1615 | });
1616 | });
1617 | describe('#getVersionNumber', function () {
1618 | it('should get the major version number from a github standard version string', () => {
1619 | let expectedVersion = 6;
1620 | let inputStringVersion = 'v6.0.0';
1621 |
1622 | expect(k.getVersionNumber(inputStringVersion)).to.equal(expectedVersion);
1623 | });
1624 | });
1625 | describe('#getImpedanceSetter', function () {
1626 | describe('channel input selection works', function () {
1627 | it('channel 2', function (done) {
1628 | k.getImpedanceSetter(2, false, false).then(function (arrayOfCommands) {
1629 | arrayOfCommands[1].should.equal('2');
1630 | done();
1631 | }).catch(function (err) {
1632 | done(err);
1633 | });
1634 | });
1635 | it('channel 5', function (done) {
1636 | k.getImpedanceSetter(5, false, false).then(function (arrayOfCommands) {
1637 | arrayOfCommands[1].should.equal('5');
1638 | done();
1639 | }).catch(function (err) {
1640 | done(err);
1641 | });
1642 | });
1643 | it('channel 9', function (done) {
1644 | k.getImpedanceSetter(9, false, false).then(function (arrayOfCommands) {
1645 | arrayOfCommands[1].should.equal('Q');
1646 | done();
1647 | }).catch(function (err) {
1648 | done(err);
1649 | });
1650 | });
1651 | it('channel 15', function (done) {
1652 | k.getImpedanceSetter(15, false, false).then(function (arrayOfCommands) {
1653 | arrayOfCommands[1].should.equal('U');
1654 | done();
1655 | }).catch(function (err) {
1656 | done(err);
1657 | });
1658 | });
1659 | it('Invalid channel selection', function (done) {
1660 | k.getImpedanceSetter(0, false, false).should.be.rejected.and.notify(done);
1661 | });
1662 | it('Invalid type', function (done) {
1663 | k.getImpedanceSetter('1', false, false).should.be.rejected.and.notify(done);
1664 | });
1665 | });
1666 | describe('P Input selection works', function () {
1667 | it('Test Signal Applied', function (done) {
1668 | k.getImpedanceSetter(1, true, false).then(function (arrayOfCommands) {
1669 | arrayOfCommands[2].should.equal('1');
1670 | done();
1671 | }).catch(function (err) {
1672 | done(err);
1673 | });
1674 | });
1675 | it('Test Signal Not Applied', function (done) {
1676 | k.getImpedanceSetter(1, false, false).then(function (arrayOfCommands) {
1677 | console.log('\n\n\narray: ' + arrayOfCommands + '\n\n\n');
1678 | arrayOfCommands[2].should.equal('0');
1679 | done();
1680 | }).catch(function (err) {
1681 | done(err);
1682 | });
1683 | });
1684 | it('Invalid type', function (done) {
1685 | k.getImpedanceSetter(1, 'taco', false).should.be.rejected.and.notify(done);
1686 | });
1687 | });
1688 | describe('N Input selection works', function () {
1689 | it('Test Signal Applied', function (done) {
1690 | k.getImpedanceSetter(1, false, true).then(function (arrayOfCommands) {
1691 | arrayOfCommands[3].should.equal('1');
1692 | done();
1693 | }).catch(function (err) {
1694 | done(err);
1695 | });
1696 | });
1697 | it('Test Signal Not Applied', function (done) {
1698 | k.getImpedanceSetter(1, false, false).then(function (arrayOfCommands) {
1699 | arrayOfCommands[3].should.equal('0');
1700 | done();
1701 | }).catch(function (err) {
1702 | done(err);
1703 | });
1704 | });
1705 | it('Invalid type', function (done) {
1706 | k.getImpedanceSetter(1, false, 'taco').should.be.rejected.and.notify(done);
1707 | });
1708 | });
1709 | describe('Prefix and postfix commands work', function () {
1710 | it('Set', function (done) {
1711 | k.getImpedanceSetter(1, true, true).then(function (arrayOfCommands) {
1712 | arrayOfCommands[0].should.equal('z');
1713 | done();
1714 | }).catch(function (err) {
1715 | done(err);
1716 | });
1717 | });
1718 | it('Latch', function (done) {
1719 | k.getImpedanceSetter(1, true, true).then(function (arrayOfCommands) {
1720 | arrayOfCommands[4].should.equal('Z');
1721 | done();
1722 | }).catch(function (err) {
1723 | done(err);
1724 | });
1725 | });
1726 | });
1727 | });
1728 | describe('sampleRateSetter', function () {
1729 | it('Works for ganglion', function (done) {
1730 | k.getSampleRateSetter('ganglion', 200).then(function (arrayOfCommands) {
1731 | arrayOfCommands[0].should.equal('~');
1732 | arrayOfCommands[1].should.equal('7');
1733 | done();
1734 | }).catch(function (err) {
1735 | done(err);
1736 | });
1737 | });
1738 | it('Works for cyton', function (done) {
1739 | k.getSampleRateSetter('cyton', 250).then(function (arrayOfCommands) {
1740 | arrayOfCommands[0].should.equal('~');
1741 | arrayOfCommands[1].should.equal('6');
1742 | done();
1743 | }).catch(function (err) {
1744 | done(err);
1745 | });
1746 | });
1747 | it('Works for daisy', function (done) {
1748 | k.getSampleRateSetter('daisy', 1000).then(function (arrayOfCommands) {
1749 | arrayOfCommands[0].should.equal('~');
1750 | arrayOfCommands[1].should.equal('4');
1751 | done();
1752 | }).catch(function (err) {
1753 | done(err);
1754 | });
1755 | });
1756 | it('Invalid board type', function (done) {
1757 | k.getSampleRateSetter('taco', 1600).should.be.rejected.and.notify(done);
1758 | });
1759 | it('Invalid board type type', function (done) {
1760 | k.getSampleRateSetter(10, 1600).should.be.rejected.and.notify(done);
1761 | });
1762 | it('Invalid sample rate type', function (done) {
1763 | k.getSampleRateSetter('daisy', 'taco').should.be.rejected.and.notify(done);
1764 | });
1765 | });
1766 | describe('boardModeSetter', function () {
1767 | it('Works for good args', function (done) {
1768 | k.getBoardModeSetter('default').then(function (arrayOfCommands) {
1769 | arrayOfCommands[0].should.equal('/');
1770 | arrayOfCommands[1].should.equal('0');
1771 | done();
1772 | }).catch(function (err) {
1773 | done(err);
1774 | });
1775 | });
1776 | it('bad board mode', function (done) {
1777 | k.getBoardModeSetter('daisy').should.be.rejected.and.notify(done);
1778 | });
1779 | it('Invalid board mode type', function (done) {
1780 | k.getBoardModeSetter(10).should.be.rejected.and.notify(done);
1781 | });
1782 | });
1783 | describe('fun funcs', function () {
1784 | describe('#isNumber', function () {
1785 | it('should return true for object of named type', function () {
1786 | expect(k.isNumber(1)).to.equal(true);
1787 | });
1788 | it('should return false for not of named type', function () {
1789 | expect(k.isNumber('taco')).to.equal(false);
1790 | });
1791 | });
1792 | describe('#isBoolean', function () {
1793 | it('should return true for object of named type', function () {
1794 | expect(k.isBoolean(true)).to.equal(true);
1795 | });
1796 | it('should return false for not of named type', function () {
1797 | expect(k.isBoolean('taco')).to.equal(false);
1798 | });
1799 | });
1800 | describe('#isString', function () {
1801 | it('should return true for object of named type', function () {
1802 | expect(k.isString('taco')).to.equal(true);
1803 | });
1804 | it('should return false for not of named type', function () {
1805 | expect(k.isString(1)).to.equal(false);
1806 | });
1807 | });
1808 | describe('#isUndefined', function () {
1809 | it('should return true for object of named type', function () {
1810 | expect(k.isUndefined()).to.equal(true);
1811 | });
1812 | it('should return false for not of named type', function () {
1813 | expect(k.isUndefined('im here')).to.equal(false);
1814 | });
1815 | });
1816 | describe('#isNull', function () {
1817 | it('should return true for object of named type', function () {
1818 | expect(k.isNull(null)).to.equal(true);
1819 | });
1820 | it('should return false for not of named type', function () {
1821 | expect(k.isNull()).to.equal(false);
1822 | });
1823 | it('should return false for not of named type', function () {
1824 | expect(k.isNull('taco')).to.equal(false);
1825 | });
1826 | });
1827 | });
1828 | describe('Emitters', function () {
1829 | it('Event Emitter Accelerometer', function () {
1830 | assert.equal('accelerometer', k.OBCIEmitterAccelerometer);
1831 | });
1832 | it('Event Emitter BLE Powered On', function () {
1833 | assert.equal('blePoweredOn', k.OBCIEmitterBlePoweredUp);
1834 | });
1835 | it('Event Emitter Close', function () {
1836 | assert.equal('close', k.OBCIEmitterClose);
1837 | });
1838 | it('Event Emitter Dropped Packet', function () {
1839 | assert.equal('droppedPacket', k.OBCIEmitterDroppedPacket);
1840 | });
1841 | it('Event Emitter EOT', function () {
1842 | assert.equal('eot', k.OBCIEmitterEot);
1843 | });
1844 | it('Event Emitter Error', function () {
1845 | assert.equal('error', k.OBCIEmitterError);
1846 | });
1847 | it('Event Emitter Ganglion Found', function () {
1848 | assert.equal('ganglionFound', k.OBCIEmitterGanglionFound);
1849 | });
1850 | it('Event Emitter Hard Set', function () {
1851 | assert.equal('hardSet', k.OBCIEmitterHardSet);
1852 | });
1853 | it('Event Emitter Impedance', function () {
1854 | assert.equal('impedance', k.OBCIEmitterImpedance);
1855 | });
1856 | it('Event Emitter Impedance Array', function () {
1857 | assert.equal('impedanceArray', k.OBCIEmitterImpedanceArray);
1858 | });
1859 | it('Event Emitter Message', function () {
1860 | assert.equal('message', k.OBCIEmitterMessage);
1861 | });
1862 | it('Event Emitter Query', function () {
1863 | assert.equal('query', k.OBCIEmitterQuery);
1864 | });
1865 | it('Event Emitter Raw Data Packet', function () {
1866 | assert.equal('rawDataPacket', k.OBCIEmitterRawDataPacket);
1867 | });
1868 | it('Event Emitter Ready', function () {
1869 | assert.equal('ready', k.OBCIEmitterReady);
1870 | });
1871 | it('Event Emitter RFduino', function () {
1872 | assert.equal('rfduino', k.OBCIEmitterRFduino);
1873 | });
1874 | it('Event Emitter Sample', function () {
1875 | assert.equal('sample', k.OBCIEmitterSample);
1876 | });
1877 | it('Event Emitter Scan Stopped', function () {
1878 | assert.equal('scanStopped', k.OBCIEmitterScanStopped);
1879 | });
1880 | it('Event Emitter Synced', function () {
1881 | assert.equal('synced', k.OBCIEmitterSynced);
1882 | });
1883 | });
1884 | describe('Errors', function () {
1885 | it('errorInvalidByteLength', function () {
1886 | assert.equal(k.OBCIErrorInvalidByteLength, 'Invalid Packet Byte Length');
1887 | });
1888 | it('errorInvalidByteStart', function () {
1889 | assert.equal(k.OBCIErrorInvalidByteStart, 'Invalid Start Byte');
1890 | });
1891 | it('errorInvalidByteStop', function () {
1892 | assert.equal(k.OBCIErrorInvalidByteStop, 'Invalid Stop Byte');
1893 | });
1894 | it('OBCIErrorInvalidData', function () {
1895 | assert.equal(k.OBCIErrorInvalidData, 'Invalid data - try again');
1896 | });
1897 | it('errorInvalidType', function () {
1898 | assert.equal(k.OBCIErrorInvalidType, 'Invalid type - check comments for input type');
1899 | });
1900 | it('errorMissingRegisterSetting', function () {
1901 | assert.equal(k.OBCIErrorMissingRegisterSetting, 'Missing register setting');
1902 | });
1903 | it('errorMissingRequiredProperty', function () {
1904 | assert.equal(k.OBCIErrorMissingRequiredProperty, 'Missing property in JSON');
1905 | });
1906 | it('errorNobleAlreadyScanning', function () {
1907 | assert.equal(k.OBCIErrorNobleAlreadyScanning, 'Scan already under way');
1908 | });
1909 | it('errorNobleNotAlreadyScanning', function () {
1910 | assert.equal(k.OBCIErrorNobleNotAlreadyScanning, 'No scan started');
1911 | });
1912 | it('errorNobleNotInPoweredOnState', function () {
1913 | assert.equal(k.OBCIErrorNobleNotInPoweredOnState, 'Please turn blue tooth on.');
1914 | });
1915 | it('errorTimeSyncIsNull', function () {
1916 | assert.equal(k.OBCIErrorTimeSyncIsNull, "'this.sync.curSyncObj' must not be null");
1917 | });
1918 | it('errorTimeSyncNoComma', function () {
1919 | assert.equal(k.OBCIErrorTimeSyncNoComma, 'Missed the time sync sent confirmation. Try sync again');
1920 | });
1921 | it('errorUndefinedOrNullInput', function () {
1922 | assert.equal(k.OBCIErrorUndefinedOrNullInput, 'Undefined or Null Input');
1923 | });
1924 | });
1925 | describe('Packet Size', function () {
1926 | it('Standard packet size', function () {
1927 | assert.equal(33, k.OBCIPacketSize);
1928 | });
1929 | it('Cyton BLE packet size', function () {
1930 | assert.equal(20, k.OBCIPacketSizeBLECyton);
1931 | });
1932 | it('Small packet size', function () {
1933 | assert.equal(12, k.OBCIPacketSizeBLERaw);
1934 | });
1935 | });
1936 | describe('Register Query on Cyton', function () {
1937 | assert.equal(k.OBCIRegisterQueryAccelerometerFirmwareV1, '\nLIS3DH Registers\n0x07.0\n0x08.0\n0x09.0\n0x0A.0\n0x0B.0\n0x0C.0\n0x0D.0\n0x0E.0\n0x0F.33\n\n0x1F.0\n0x20.8\n0x21.0\n0x22.0\n0x23.18\n0x24.0\n0x25.0\n0x26.0\n0x27.0\n0x28.0\n0x29.0\n0x2A.0\n0x2B.0\n0x2C.0\n0x2D.0\n0x2E.0\n0x2F.20\n0x30.0\n0x31.0\n0x32.0\n0x33.0\n\n0x38.0\n0x39.0\n0x3A.0\n0x3B.0\n0x3C.0\n0x3D.0\n');
1938 | assert.equal(k.OBCIRegisterQueryAccelerometerFirmwareV3, '\nLIS3DH Registers\n0x07 00\n0x08 00\n0x09 00\n0x0A 00\n0x0B 00\n0x0C 00\n0x0D 00\n0x0E 00\n0x0F 33\n\n0x1F 00\n0x20 08\n0x21 00\n0x22 00\n0x23 18\n0x24 00\n0x25 00\n0x26 00\n0x27 00\n0x28 00\n0x29 00\n0x2A 00\n0x2B 00\n0x2C 00\n0x2D 00\n0x2E 00\n0x2F 20\n0x30 00\n0x31 00\n0x32 00\n0x33 00\n\n0x38 00\n0x39 00\n0x3A 00\n0x3B 00\n0x3C 00\n0x3D 00\n');
1939 | assert.equal(k.OBCIRegisterQueryCyton, '\nBoard ADS Registers\nADS_ID, 00, 3E, 0, 0, 1, 1, 1, 1, 1, 0\nCONFIG1, 01, 96, 1, 0, 0, 1, 0, 1, 1, 0\nCONFIG2, 02, C0, 1, 1, 0, 0, 0, 0, 0, 0\nCONFIG3, 03, EC, 1, 1, 1, 0, 1, 1, 0, 0\nLOFF, 04, 02, 0, 0, 0, 0, 0, 0, 1, 0\nCH1SET, 05, 68, 0, 1, 1, 0, 1, 0, 0, 0\nCH2SET, 06, 68, 0, 1, 1, 0, 1, 0, 0, 0\nCH3SET, 07, 68, 0, 1, 1, 0, 1, 0, 0, 0\nCH4SET, 08, 68, 0, 1, 1, 0, 1, 0, 0, 0\nCH5SET, 09, 68, 0, 1, 1, 0, 1, 0, 0, 0\nCH6SET, 0A, 68, 0, 1, 1, 0, 1, 0, 0, 0\nCH7SET, 0B, 68, 0, 1, 1, 0, 1, 0, 0, 0\nCH8SET, 0C, 68, 0, 1, 1, 0, 1, 0, 0, 0\nBIAS_SENSP, 0D, FF, 1, 1, 1, 1, 1, 1, 1, 1\nBIAS_SENSN, 0E, FF, 1, 1, 1, 1, 1, 1, 1, 1\nLOFF_SENSP, 0F, 00, 0, 0, 0, 0, 0, 0, 0, 0\nLOFF_SENSN, 10, 00, 0, 0, 0, 0, 0, 0, 0, 0\nLOFF_FLIP, 11, 00, 0, 0, 0, 0, 0, 0, 0, 0\nLOFF_STATP, 12, 00, 0, 0, 0, 0, 0, 0, 0, 0\nLOFF_STATN, 13, 00, 0, 0, 0, 0, 0, 0, 0, 0\nGPIO, 14, 0F, 0, 0, 0, 0, 1, 1, 1, 1\nMISC1, 15, 00, 0, 0, 0, 0, 0, 0, 0, 0\nMISC2, 16, 00, 0, 0, 0, 0, 0, 0, 0, 0\nCONFIG4, 17, 00, 0, 0, 0, 0, 0, 0, 0, 0\n');
1940 | assert.equal(k.OBCIRegisterQueryCytonDaisy, '\nDaisy ADS Registers\nADS_ID, 00, 3E, 0, 0, 1, 1, 1, 1, 1, 0\nCONFIG1, 01, 96, 1, 0, 0, 1, 0, 1, 1, 0\nCONFIG2, 02, C0, 1, 1, 0, 0, 0, 0, 0, 0\nCONFIG3, 03, EC, 1, 1, 1, 0, 1, 1, 0, 0\nLOFF, 04, 02, 0, 0, 0, 0, 0, 0, 1, 0\nCH1SET, 05, 68, 0, 1, 1, 0, 1, 0, 0, 0\nCH2SET, 06, 68, 0, 1, 1, 0, 1, 0, 0, 0\nCH3SET, 07, 68, 0, 1, 1, 0, 1, 0, 0, 0\nCH4SET, 08, 68, 0, 1, 1, 0, 1, 0, 0, 0\nCH5SET, 09, 68, 0, 1, 1, 0, 1, 0, 0, 0\nCH6SET, 0A, 68, 0, 1, 1, 0, 1, 0, 0, 0\nCH7SET, 0B, 68, 0, 1, 1, 0, 1, 0, 0, 0\nCH8SET, 0C, 68, 0, 1, 1, 0, 1, 0, 0, 0\nBIAS_SENSP, 0D, FF, 1, 1, 1, 1, 1, 1, 1, 1\nBIAS_SENSN, 0E, FF, 1, 1, 1, 1, 1, 1, 1, 1\nLOFF_SENSP, 0F, 00, 0, 0, 0, 0, 0, 0, 0, 0\nLOFF_SENSN, 10, 00, 0, 0, 0, 0, 0, 0, 0, 0\nLOFF_FLIP, 11, 00, 0, 0, 0, 0, 0, 0, 0, 0\nLOFF_STATP, 12, 00, 0, 0, 0, 0, 0, 0, 0, 0\nLOFF_STATN, 13, 00, 0, 0, 0, 0, 0, 0, 0, 0\nGPIO, 14, 0F, 0, 0, 0, 0, 1, 1, 1, 1\nMISC1, 15, 00, 0, 0, 0, 0, 0, 0, 0, 0\nMISC2, 16, 00, 0, 0, 0, 0, 0, 0, 0, 0\nCONFIG4, 17, 00, 0, 0, 0, 0, 0, 0, 0, 0\n');
1941 | assert.equal(k.OBCIRegisterQuerySizeCytonFirmwareV1, k.OBCIRegisterQueryCyton.length + k.OBCIRegisterQueryAccelerometerFirmwareV1.length);
1942 | assert.equal(k.OBCIRegisterQuerySizeCytonDaisyFirmwareV1, k.OBCIRegisterQueryCyton.length + k.OBCIRegisterQueryCytonDaisy.length + k.OBCIRegisterQueryAccelerometerFirmwareV1.length);
1943 | assert.equal(k.OBCIRegisterQuerySizeCytonFirmwareV3, k.OBCIRegisterQueryCyton.length + k.OBCIRegisterQueryAccelerometerFirmwareV3.length);
1944 | assert.equal(k.OBCIRegisterQuerySizeCytonDaisyFirmwareV3, k.OBCIRegisterQueryCyton.length + k.OBCIRegisterQueryCytonDaisy.length + k.OBCIRegisterQueryAccelerometerFirmwareV3.length);
1945 | assert.equal(k.OBCIRegisterQueryNameMISC1, 'MISC1');
1946 | assert.equal(k.OBCIRegisterQueryNameBIASSENSP, 'BIAS_SENSP');
1947 | assert.equal(k.OBCIRegisterQueryNameCHnSET[0], 'CH1SET');
1948 | assert.equal(k.OBCIRegisterQueryNameCHnSET[1], 'CH2SET');
1949 | assert.equal(k.OBCIRegisterQueryNameCHnSET[2], 'CH3SET');
1950 | assert.equal(k.OBCIRegisterQueryNameCHnSET[3], 'CH4SET');
1951 | assert.equal(k.OBCIRegisterQueryNameCHnSET[4], 'CH5SET');
1952 | assert.equal(k.OBCIRegisterQueryNameCHnSET[5], 'CH6SET');
1953 | assert.equal(k.OBCIRegisterQueryNameCHnSET[6], 'CH7SET');
1954 | assert.equal(k.OBCIRegisterQueryNameCHnSET[7], 'CH8SET');
1955 | });
1956 | describe('General', function () {
1957 | it('Ganglion prefix', function () {
1958 | assert.equal('Ganglion', k.OBCIGanglionPrefix);
1959 | });
1960 | it('Ganglion ble search time', function () {
1961 | assert.equal(0.016, k.OBCIGanglionAccelScaleFactor);
1962 | });
1963 | it('Ganglion ble search time', function () {
1964 | assert.equal(20000, k.OBCIGanglionBleSearchTime);
1965 | });
1966 | it('packet size', function () {
1967 | assert.equal(20, k.OBCIGanglionPacketSize);
1968 | });
1969 | it('samples per packet', function () {
1970 | assert.equal(2, k.OBCIGanglionSamplesPerPacket);
1971 | });
1972 | it('packet positions 18 bit', function () {
1973 | expect(k.OBCIGanglionPacket18Bit).to.deep.equal({
1974 | auxByte: 20,
1975 | byteId: 0,
1976 | dataStart: 1,
1977 | dataStop: 19
1978 | });
1979 | });
1980 | it('packet positions 19 bit', function () {
1981 | expect(k.OBCIGanglionPacket19Bit).to.deep.equal({
1982 | byteId: 0,
1983 | dataStart: 1,
1984 | dataStop: 20
1985 | });
1986 | });
1987 | });
1988 | describe('Commands', function () {
1989 | it('Synthetic data mode enable', function () {
1990 | assert.equal('t', k.OBCIGanglionSyntheticDataEnable);
1991 | });
1992 | it('Synthetic data mode disable', function () {
1993 | assert.equal('T', k.OBCIGanglionSyntheticDataDisable);
1994 | });
1995 | it('Impedance start', function () {
1996 | assert.equal('z', k.OBCIGanglionImpedanceStart);
1997 | });
1998 | it('Impedance stop', function () {
1999 | assert.equal('Z', k.OBCIGanglionImpedanceStop);
2000 | });
2001 | });
2002 | describe('Byte Id', function () {
2003 | it('Uncompressed', function () {
2004 | assert.equal(0, k.OBCIGanglionByteIdUncompressed);
2005 | });
2006 | it('should have correct values for 18 bit', function () {
2007 | expect(k.OBCIGanglionByteId18Bit).to.deep.equal({
2008 | max: 100,
2009 | min: 1
2010 | });
2011 | });
2012 | it('should have correct values for 18 bit', function () {
2013 | expect(k.OBCIGanglionByteId19Bit).to.deep.equal({
2014 | max: 200,
2015 | min: 101
2016 | });
2017 | });
2018 | it('Impedance channel 1', function () {
2019 | assert.equal(201, k.OBCIGanglionByteIdImpedanceChannel1);
2020 | });
2021 | it('Impedance channel 2', function () {
2022 | assert.equal(202, k.OBCIGanglionByteIdImpedanceChannel2);
2023 | });
2024 | it('Impedance channel 3', function () {
2025 | assert.equal(203, k.OBCIGanglionByteIdImpedanceChannel3);
2026 | });
2027 | it('Impedance channel 4', function () {
2028 | assert.equal(204, k.OBCIGanglionByteIdImpedanceChannel4);
2029 | });
2030 | it('Impedance channel reference', function () {
2031 | assert.equal(205, k.OBCIGanglionByteIdImpedanceChannelReference);
2032 | });
2033 | it('Multi packet', function () {
2034 | assert.equal(206, k.OBCIGanglionByteIdMultiPacket);
2035 | });
2036 | it('Multi packet stop', function () {
2037 | assert.equal(207, k.OBCIGanglionByteIdMultiPacketStop);
2038 | });
2039 | });
2040 | describe('simblee', function () {
2041 | it('Service', function () {
2042 | assert.equal('fe84', k.SimbleeUuidService);
2043 | });
2044 | it('Receive', function () {
2045 | assert.equal('2d30c082f39f4ce6923f3484ea480596', k.SimbleeUuidReceive);
2046 | });
2047 | it('Write', function () {
2048 | assert.equal('2d30c083f39f4ce6923f3484ea480596', k.SimbleeUuidSend);
2049 | });
2050 | it('Disconnect', function () {
2051 | assert.equal('2d30c084f39f4ce6923f3484ea480596', k.SimbleeUuidDisconnect);
2052 | });
2053 | });
2054 | describe('RFduino BLE UUID', function () {
2055 | it('Service', function () {
2056 | assert.equal(k.RFduinoUuidService, '2220');
2057 | });
2058 | it('Receive', function () {
2059 | assert.equal(k.RFduinoUuidReceive, '2221');
2060 | });
2061 | it('Write/Notify/Subscribe', function () {
2062 | assert.equal(k.RFduinoUuidSend, '2222');
2063 | });
2064 | it('supposed to be a send but can\'t get it working', function () {
2065 | assert.equal(k.RFduinoUuidSendTwo, '2223');
2066 | });
2067 | });
2068 | describe('Cyton BLE', function () {
2069 | it('3 samples per packet', function () {
2070 | assert.equal(k.OBCICytonBLESamplesPerPacket, 3);
2071 | });
2072 | });
2073 | describe('noble', function () {
2074 | it('Peripheral Connect', function () {
2075 | assert.equal('connect', k.OBCINobleEmitterPeripheralConnect);
2076 | });
2077 | it('Peripheral Disconnect', function () {
2078 | assert.equal('disconnect', k.OBCINobleEmitterPeripheralDisconnect);
2079 | });
2080 | it('Peripheral Discover', function () {
2081 | assert.equal('discover', k.OBCINobleEmitterPeripheralDiscover);
2082 | });
2083 | it('Peripheral Services Discover', function () {
2084 | assert.equal('servicesDiscover', k.OBCINobleEmitterPeripheralServicesDiscover);
2085 | });
2086 | it('Service Characteristics Discover', function () {
2087 | assert.equal('characteristicsDiscover', k.OBCINobleEmitterServiceCharacteristicsDiscover);
2088 | });
2089 | it('Service Read', function () {
2090 | assert.equal('read', k.OBCINobleEmitterServiceRead);
2091 | });
2092 | it('Discover', function () {
2093 | assert.equal('discover', k.OBCINobleEmitterDiscover);
2094 | });
2095 | it('Scan Start', function () {
2096 | assert.equal('scanStart', k.OBCINobleEmitterScanStart);
2097 | });
2098 | it('Scan Stop', function () {
2099 | assert.equal('scanStop', k.OBCINobleEmitterScanStop);
2100 | });
2101 | it('State Change', function () {
2102 | assert.equal('stateChange', k.OBCINobleEmitterStateChange);
2103 | });
2104 | it('State Powered On', function () {
2105 | assert.equal('poweredOn', k.OBCINobleStatePoweredOn);
2106 | });
2107 | });
2108 | describe('#getPeripheralLocalNames', function () {
2109 | it('should resolve a list of localNames from an array of peripherals', function (done) {
2110 | let numPerifs = 3;
2111 | let perifs = getListOfPeripheralsOfSize(numPerifs);
2112 | k.getPeripheralLocalNames(perifs).then(list => {
2113 | expect(list.length).to.equal(numPerifs);
2114 | for (let i = 0; i < list.length; i++) {
2115 | expect(list[i]).to.equal(makeLocalName(i));
2116 | }
2117 | done();
2118 | }).catch(done);
2119 | });
2120 | it('should reject if array is empty', function (done) {
2121 | k.getPeripheralLocalNames([]).should.be.rejected.and.notify(done);
2122 | });
2123 | });
2124 | describe('#getPeripheralWithLocalName', function () {
2125 | it('should resovle a peripheral with local name', function (done) {
2126 | let numOfPerifs = 4;
2127 | let perifs = getListOfPeripheralsOfSize(numOfPerifs);
2128 | // console.log('perifs', perifs)
2129 | let goodName = makeLocalName(numOfPerifs - 1); // Will be in the list
2130 | // console.log(`goodName: ${goodName}`)
2131 | k.getPeripheralWithLocalName(perifs, goodName).should.be.fulfilled.and.notify(done);
2132 | });
2133 | it('should reject if local name is not in perif list', function (done) {
2134 | let numOfPerifs = 4;
2135 | let perifs = getListOfPeripheralsOfSize(numOfPerifs);
2136 | let badName = makeLocalName(numOfPerifs + 2); // Garuenteed to not be in the list
2137 | k.getPeripheralWithLocalName(perifs, badName).should.be.rejected.and.notify(done);
2138 | });
2139 | it('should reject if pArray is not array local name is not in perif list', function (done) {
2140 | let badName = makeLocalName(1); // Garuenteed to not be in the list
2141 | k.getPeripheralWithLocalName(badName).should.be.rejected.and.notify(done);
2142 | });
2143 | });
2144 | describe('#isPeripheralGanglion', function () {
2145 | it('should return true when proper localName', function () {
2146 | let list = getListOfPeripheralsOfSize(1);
2147 | let perif = list[0];
2148 | expect(k.isPeripheralGanglion(perif)).to.equal(true);
2149 | });
2150 | it('should return false when incorrect localName', function () {
2151 | let list = getListOfPeripheralsOfSize(1);
2152 | let perif = list[0];
2153 | perif.advertisement.localName = 'burrito';
2154 | expect(k.isPeripheralGanglion(perif)).to.equal(false);
2155 | });
2156 | it('should return false when bad object', function () {
2157 | expect(k.isPeripheralGanglion({})).to.equal(false);
2158 | });
2159 | it('should return false if nothing input', function () {
2160 | expect(k.isPeripheralGanglion()).to.equal(false);
2161 | });
2162 | it('should return false if undfined unput input', function () {
2163 | let list = getListOfPeripheralsOfSize(1);
2164 | let perif = list[0];
2165 | perif.advertisement.localName = undefined;
2166 | expect(k.isPeripheralGanglion(perif)).to.equal(false);
2167 | });
2168 | it('should return false when missing advertisement object', function () {
2169 | let list = getListOfPeripheralsOfSize(1);
2170 | let perif = list[0];
2171 | perif.advertisement = null;
2172 | expect(k.isPeripheralGanglion(perif)).to.equal(false);
2173 | });
2174 | });
2175 | });
2176 |
--------------------------------------------------------------------------------
/test/timingEventsAsPromises.js:
--------------------------------------------------------------------------------
1 | // Converts timing events to use promises, to gain bluebird's checks
2 |
3 | function instrumentTimingEvents (module, type) {
4 | // replaces module[type] with a function that does the same thing but uses a promise
5 | // assumes the first argument will be to a callback function
6 |
7 | // if this a setSomething function with a clearSomething partner, the partner will also be instrumented
8 | var setName = type;
9 | var clearName = null;
10 | if (type.substring(0, 3) === 'set') {
11 | clearName = 'clear' + type.substring(3);
12 | }
13 |
14 | if (!module[setName]) return;
15 |
16 | // store original functions
17 | var originalSet = module[setName];
18 | var originalClear = module[clearName];
19 | exports[setName + 'Ignored'] = originalSet;
20 |
21 | // dictionary to store promise details for each call
22 | var events = {};
23 |
24 | // setAsPromise() is the brunt of the function. It replaces the previous global function,
25 | // and sets up a promise to resolve when the callback is called
26 | var eventCount = 0;
27 | var setAsPromise = function (callback) {
28 | var args = [].slice.call(arguments);
29 |
30 | var eventNum = ++eventCount;
31 | var eventHandle;
32 |
33 | if (setAsPromise._ignoreCount > 0) {
34 | --setAsPromise._ignoreCount;
35 |
36 | return originalSet.apply(this, args);
37 | }
38 |
39 | // actual callback is replaced by promise resolve
40 | args[0] = function () {
41 | if (!events[eventNum]) throw new Error(setName + ' ' + eventNum + ' disappeared');
42 | events[eventNum].resolve([].slice.call(arguments));
43 | };
44 |
45 | eventHandle = originalSet.apply(this, args) || eventNum;
46 |
47 | // this portion is a function so that setInterval may be handled via recursion
48 | function dispatch () {
49 | var handlerDetails = { handle: eventHandle };
50 |
51 | var promise = new Promise((resolve, reject) => {
52 | handlerDetails.resolve = resolve;
53 | handlerDetails.reject = reject;
54 | });
55 |
56 | handlerDetails.promise = promise;
57 | events[eventNum] = handlerDetails;
58 |
59 | promise.then(function (argumentArray) {
60 | if (type !== 'setInterval') {
61 | delete events[eventNum];
62 | } else {
63 | dispatch();
64 | }
65 |
66 | // call original handler
67 | callback.apply(this, argumentArray);
68 | }, () => {
69 | originalClear(eventHandle);
70 | delete events[eventNum];
71 | });
72 |
73 | return promise;
74 | }
75 |
76 | dispatch();
77 |
78 | return eventNum;
79 | };
80 |
81 | // actually replace functions with instrumented ones
82 | setAsPromise._ignoreCount = 0;
83 | module[setName] = setAsPromise;
84 | Object.defineProperty(setAsPromise, 'name', { value: setName + 'AsPromise' });
85 |
86 | if (clearName) {
87 | module[clearName] = (eventNum) => {
88 | if (!events[eventNum]) {
89 | originalClear(eventNum);
90 | } else {
91 | events[eventNum].reject(new Error('cleared'));
92 | }
93 | };
94 | Object.defineProperty(module[clearName], 'name', { value: clearName + 'AsPromise' });
95 | }
96 | }
97 |
98 | instrumentTimingEvents(global, 'setTimeout');
99 | instrumentTimingEvents(global, 'setInterval');
100 | instrumentTimingEvents(global, 'setImmediate');
101 | // // Possible TODO: nextTick needs some exceptions included to prevent infinite recursion
102 | // instrumentTimingEvents(process, 'nextTick');
103 |
104 | // the next call to the passed function should not be promisified
105 | // may be queued multiple times
106 | exports.ignoreOnce = (ignored) => {
107 | ignored._ignoreCount ++;
108 | };
109 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | const library = 'OpenBCIUtilities';
4 | const librarySnakeCase = 'openbci-utilities';
5 | const libraryExport = 'default';
6 |
7 | const config = {
8 | entry: {
9 | [librarySnakeCase]: './src/index.js',
10 | utilities: './src/utilities.js',
11 | constants: './src/constants.js',
12 | debug: './src/debug.js'
13 | },
14 | module: {
15 | rules: [
16 | {
17 | test: /\.js$/,
18 | exclude: /(node_modules)/,
19 | use: {
20 | loader: 'babel-loader'
21 | }
22 | }
23 | ]
24 | },
25 | devtool: 'eval',
26 | devServer: {
27 | compress: true,
28 | port: 9000
29 | }
30 | };
31 |
32 | const exportLibraryTarget = (libraryTarget, name) =>
33 | Object.assign({}, config, {
34 | output: {
35 | path: path.resolve(__dirname, 'dist'),
36 | filename: `${name}.js`,
37 | library,
38 | libraryTarget,
39 | libraryExport
40 | }
41 | });
42 |
43 | module.exports = [
44 | exportLibraryTarget('umd', '[name]'),
45 | exportLibraryTarget('var', '[name].var')
46 | ];
47 |
--------------------------------------------------------------------------------