Comparar commits

...

159 Commits

Autor SHA1 Mensagem Data
AJ Keller d4f62ef382 Merge pull request #96 from OpenBCI/1.4.0
1.4.0
2016-10-31 19:49:39 -04:00
AJ Keller c4e29bbaa7 Merge pull request #117 from aj-ptw/fix-promise-data-processing
Fix promise data processing
2016-10-31 19:25:15 -04:00
AJ Keller f553cdea35 Fix: Remove promise functions from all internal data processing events. 2016-10-31 19:14:24 -04:00
AJ Keller 25c7871fec Merge pull request #111 from baffo32/1.4.x-socket-close-resources
Fix connection-related leaks and inconsistencies
2016-10-30 21:58:45 -04:00
Karl Semich c2097670e7 Use bluebird to detect runaway promises and timing events.
Plug most runaway tasks, and some other issues, raised by the new infrastructure.
2016-10-31 00:35:59 +00:00
Karl Semich cfb8071a9d Improvements for SNTP robustness and occasional test failures
Also added an unrelated test to improve coverage
2016-10-31 00:26:10 +00:00
Karl Semich 22aca53dac New API functions: .isConnected() .isStreaming()
All checks for connection state are normalized to use it.

The name `.connected()` may have been more consistent with the rest of
the library, but it would incorrectly evaluate to true in code that
used the old, undocumented `.connected` field, generating hard-to-find
bugs.  So `isConnected()` was chosen to avoid that situation.
2016-10-31 00:04:36 +00:00
Karl Semich 9467d8a052 Add unified _disconnected() function to handle serial cleanup
also mark _reset function which sounds important but does nothing
2016-10-31 00:01:26 +00:00
Karl Semich b6ef09c220 Add tests verifying connection/disconnection state 2016-10-30 23:59:49 +00:00
AJ Keller 238d4cc119 contributing update (#110)
* Update README.md
2016-10-22 22:20:14 -04:00
AJ Keller c59cd18cf4 Merge pull request #107 from baffo32/1.4.x-debugging-packet-dump
Added a debug option to dump serial traffic
2016-10-21 10:15:32 -04:00
Karl Semich 69cd84f446 Merge branch '1.4.0' into 1.4.x-debugging-packet-dump 2016-10-21 09:32:44 +00:00
AJ Keller 9a17e41c0b Merge pull request #108 from baffo32/1.4.x-throw-invalid-options
Throw an error if invalid options are passed
2016-10-21 00:56:20 -04:00
Karl Semich edff39504c Use backticks in changelog from other pull review 2016-10-21 04:00:42 +00:00
Karl Semich 2d1285a887 Merge branch '1.4.0' into 1.4.x-throw-invalid-options 2016-10-21 03:42:02 +00:00
Karl Semich 2100aaee5c Changelog updates per PR review 2016-10-21 03:41:00 +00:00
Karl Semich eba46f8e6c debugBytes fixups, pull review 2016-10-21 03:35:09 +00:00
AJ Keller de57563f51 Merge pull request #109 from baffo32/1.4.x-double-connection 2016-10-20 13:32:42 -04:00
Karl Semich f59b41109d Connection fails if already connected (fixes #93)
Resources were not being cleaned up previously.
Although failing is somewhat harsh, this fix makes possible errors more visible.
2016-10-20 13:10:05 +00:00
Karl Semich 0193031d20 Add tests for debug option 2016-10-20 12:20:40 +00:00
Karl Semich 2904830309 Throw an error if invalid options are passed 2016-10-20 11:49:07 +00:00
Karl Semich 08ce44d4e9 Added a debug option to dump serial traffic 2016-10-20 11:20:12 +00:00
AJ Keller 62a69e01cc Merge pull request #104 from baffo32/1.4.0-use-fragmentation-simulation
use fragmentation simulation
2016-10-20 00:35:57 -04:00
AJ Keller e9e6dbd624 Merge pull request #105 from baffo32/1.4.0-options-algorithm
Automate the interpretation of options and defaults
2016-10-19 21:53:20 -04:00
AJ Keller 1ade656876 Merge pull request #106 from baffo32/1.4.0-firmware-typo
Stop outputting v2.0.0 after reset for v1 firmware
2016-10-19 21:52:37 -04:00
Karl Semich 83d32bc9b9 Stop outputting v2.0.0 after reset for v1 firmware 2016-10-20 00:26:51 +00:00
Karl Semich 4b5e4ab0a6 Automate the interpretation of options and defaults. 2016-10-19 23:41:36 +00:00
Karl Semich 2cc0d42fdf Enable fragmentation for some tests to ensure code withstands it 2016-10-19 23:08:17 +00:00
Karl Semich 94e0a13d71 Fix off-by-one max simulated radio channel 2016-10-19 23:08:17 +00:00
AJ Keller 6b11910fa7 Merge pull request #101 from baffo32/1.4.0-simulate-fragmentation 2016-10-19 18:26:12 -04:00
Karl Semich 83ac939d4e Updated incorrect default 2016-10-19 21:15:46 +00:00
Karl Semich 38687d42bb Add test to cover random fragmentation 2016-10-19 21:11:41 +00:00
Karl Semich 1a43a06786 Per PR review, change default fragmentation to 'none'.
Also removed associated test changes, and added some missing tests.
2016-10-19 20:43:25 +00:00
Karl Semich 47c6918194 Frag test adjustment: notice time sync replies even in byte 0 of a buffer 2016-10-19 20:39:54 +00:00
Karl Semich c351f3afd1 Add test: options propagate from public api to simulator
Revealed associated bugs which I fixed
2016-10-19 15:17:05 +00:00
Karl Semich e65707cb31 Merge branch '1.4.0' into 1.4.0-simulate-fragmentation 2016-10-19 14:20:43 +00:00
Karl Semich 97e44171b8 Some tests for simulating fragmentation.
Also fixed a few miscontructed buffer calls I ran into.
2016-10-19 13:40:05 +00:00
Karl Semich 0f7bb33434 Frag test adjustment: allow multiple matches for overbuffered data 2016-10-19 11:22:03 +00:00
Karl Semich 884f2f14ee Frag test adjustment: preserve buffer when parsing reset
- fixes bug with fragmented eot after reset which would result in a freeze
- removed daisy board specification in test; after this bugfix it was actually parsed, and conflicts with next tests, which assume 8 channels
2016-10-19 11:22:02 +00:00
Karl Semich 5fde5b09bf Frag test adjustment: disable for simulator tests so they pass 2016-10-19 11:21:46 +00:00
Karl Semich 23776e4b9c Add #98 to changelog 2016-10-19 11:12:09 +00:00
Karl Semich 5b70268390 Add simulation for buffer size and latency time (fixes #63)
Also minor changes to address comments on PR #100
2016-10-19 10:57:38 +00:00
AJ Keller 37db876f11 Update README.md 2016-10-18 23:15:56 -04:00
Karl Semich 864469d3d8 Simulate packet fragmentation; fixes #100 2016-10-19 01:31:24 +00:00
AJ Keller 7d78748532 Merge pull request #98 from baffo32/1.4.0-auto-find-linux
add autoFind patterns for Linux FTDI
2016-10-16 22:59:43 -04:00
Karl Semich d6fbce3e4c add autoFind patterns for Linux FTDI 2016-10-17 01:05:47 +00:00
AJ Keller 7ecff0a08d Rebased off 1.3.3 2016-10-16 16:47:04 -04:00
AJ Keller ab891d7565 saving 2016-10-16 16:40:06 -04:00
AJ Keller 3e99a77e88 ENH semistandard lint 2016-10-16 16:40:06 -04:00
AJ Keller e3061c03ce Fix log statements 2016-10-16 16:06:03 -04:00
AJ Keller d6335257e1 Merge pull request #94 from aj-ptw/minor-patches
Fix leaked event emitter with time sync, remove extra log statement
2016-10-16 15:02:50 -04:00
AJ Keller aea599a7dd Add 4.3-4.6 and 6.4-6.8 to travis.yaml 2016-10-16 14:53:32 -04:00
AJ Keller 031861d2ed Fix leaked event emitter with time sync, remove extra log statement 2016-10-16 14:47:07 -04:00
AJ Keller 6fd9ddf01b Merge pull request #86 from aj-ptw/time-sync-example
Add example for time syncing
2016-09-29 16:15:06 -04:00
AJ Keller fe2abac07b Add example for time syncing 2016-09-29 16:10:16 -04:00
AJ Keller 2528d56ac9 Update package.json 2016-09-29 14:55:25 -04:00
AJ Keller 18b137b498 Merge pull request #85 from aj-ptw/fix-constants-constructor
Fix constants not set in constructor
2016-09-29 14:52:50 -04:00
AJ Keller 470ee81928 Fix constants not set in constructor 2016-09-29 14:44:59 -04:00
AJ Keller 3c46100e1d Merge pull request #84 from aj-ptw/dropped-packet-alert
Add dropped packet detection
2016-09-29 10:26:50 -04:00
AJ Keller 2c0b2e37d2 Add dropped packet detection 2016-09-29 10:22:02 -04:00
AJ Keller 094e328296 Merge pull request #78 from aj-ptw/enh-pdf-readme
ENH readme gets a table of contents
2016-08-21 12:15:21 -04:00
AJ Keller 4c9bbb1f6d ENH readme gets a table of contents 2016-08-19 13:50:34 -04:00
AJ Keller b51cb54f92 Merge pull request #74 from pushtheworldllc/serialport-upgrade
Enh upgrade serial port to 4.x
2016-08-10 07:35:38 -04:00
AJ Keller 19f05e362f Enh upgrade serial port to 4.x 2016-08-09 22:31:36 -04:00
AJ Keller c33d08b486 Merge pull request #73 from pushtheworldllc/dev-firmware
v1.2.1 Fix for radio channel set functions
2016-08-08 22:42:36 -04:00
AJ Keller 97cff2dac9 Fix for radio channel set functions 2016-08-08 22:36:09 -04:00
AJ Keller 6cf5e993ed Merge pull request #72 from pushtheworldllc/dev
Update time synced accel packets
2016-08-04 17:35:04 -04:00
AJ Keller 6cbf99e635 Update for time sync accel sending in 7,8,9 and not 0,1,2
Update for new firmware

update readme and changelog for 1.2

Readme and comment patches from teon comments on PR #70

update readme

update readme
2016-08-04 13:37:47 -04:00
AJ Keller 9bd1121ab8 Merge pull request #71 from haniawni/OpenBCI
Explain Interfacing with LSL
2016-08-03 17:13:15 -04:00
HaniAwni 7d878f1a16 Explain Interfacing with LSL 2016-08-03 13:55:53 -07:00
AJ Keller ba4370793c Merge pull request #70 from pushtheworldllc/bug-time-sync
Bug time sync
2016-07-28 15:41:22 -04:00
AJ Keller e88922c106 Fix auto test for commandChannelOn 2016-07-25 22:01:48 -04:00
AJ Keller a43c52fdec Add auto test for syncClocksFull 2016-07-25 20:21:15 -04:00
AJ Keller 5cf97383b9 Fix time sync, enh to readme, add full sync function
Saving

Time offset back to working in auto tests

All tests passing with time sync func

time sync working

Add examples in readme.

General enh and clean up
2016-07-25 17:10:02 -04:00
AJ Keller d51c8f80d4 Merge pull request #69 from OpenBCI/teonbrooks-patch-1
Update package.json
2016-07-25 08:54:22 -04:00
AJ Keller 0a1f3de1a7 Update badges for new repo name 2016-07-19 10:26:39 -04:00
Teon L Brooks e68f85d5b3 Update package.json 2016-07-18 15:06:28 -04:00
Teon L Brooks 9c51fd673e Merge pull request #64 from pushtheworldllc/dev-ntp
ADD all OpenBCI board features, ADD daisy support, ADD firmware 2.0
2016-07-18 14:52:42 -04:00
AJ Keller 2cf1a46994 Update readme for Teon fixes 2016-07-18 13:35:06 -04:00
AJ Keller 77f7946790 Add tutorial for time sync 2016-07-17 21:06:16 -04:00
AJ Keller 9bd83aaf15 Fix sample bug and time sync bug 2016-07-17 19:45:04 -04:00
AJ Keller 22f5ddbcef Enh Readme.md 2016-07-14 17:26:53 -04:00
AJ Keller 918451ebcb Saving 2016-07-14 16:40:18 -04:00
AJ Keller a03250502c ENH Readme 2016-07-14 16:36:25 -04:00
AJ Keller 265e89284c Add hardware test output to ignore 2016-07-14 14:36:27 -04:00
AJ Keller 0cd2e57f96 New Time Sync Protocol 2016-07-14 14:36:27 -04:00
AJ Keller 4a58dcb36a moving to rc 2016-07-14 14:34:17 -04:00
AJ Keller 82a3fc3ced ADD daisy 2016-07-14 14:34:17 -04:00
AJ Keller 23e8364185 Saving for the night 2016-07-14 14:34:17 -04:00
AJ Keller e21160fa4d ADD tests for simulator radio commands 2016-07-14 14:34:17 -04:00
AJ Keller 6d3813c4e1 Fix version number extraction for buffer 2016-07-14 14:34:17 -04:00
AJ Keller d8342879cf Fix teon comments 2016-07-14 14:34:17 -04:00
AJ Keller 3322e9ca5c Add tests for radio board verification testing 2016-07-14 14:34:17 -04:00
AJ Keller 5f0085ddb3 Working on radio validation 2016-07-14 14:34:17 -04:00
AJ Keller a005c8b711 Auto tests on sim working for all board commands 2016-07-14 14:34:17 -04:00
AJ Keller 49d0a5376f Fix breaking build in simulator 2016-07-14 14:34:17 -04:00
AJ Keller de22e725d5 ADD time sync tests 2016-07-14 14:34:17 -04:00
AJ Keller 74cd163bd5 Simulator working for multiple packet types 2016-07-14 14:34:17 -04:00
AJ Keller 9fd53d2bec Simulator emitting time sync set packet 2016-07-14 14:34:17 -04:00
AJ Keller da8e407e84 Saving 2016-07-14 14:34:17 -04:00
AJ Keller d624b1d387 Working on time syncing 2016-07-14 14:34:17 -04:00
AJ Keller f861563326 Moved funcs from board to sample file 2016-07-14 14:34:17 -04:00
AJ Keller 083df5a109 Byte processor working better 2016-07-14 14:34:17 -04:00
AJ Keller aa5e42575a Adding test 2016-07-14 14:34:17 -04:00
AJ Keller cd482558bb saving 2016-07-14 14:34:17 -04:00
AJ Keller fa5890d5ad ADD poll time set function 2016-07-14 14:34:17 -04:00
AJ Keller 3df7d3170c Radio channel change function built 2016-07-14 14:34:17 -04:00
AJ Keller 46edd477a5 Add note to change log 2016-07-14 14:34:17 -04:00
AJ Keller c36e9d6126 Saving 2016-07-14 14:34:17 -04:00
AJ Keller ccd2983cc9 Saving 2016-07-14 14:34:17 -04:00
AJ Keller 08a575cc9c saving 2016-07-14 14:34:17 -04:00
AJ Keller 83223cb50a Add tests for every option for the main constructor 2016-07-14 14:34:17 -04:00
AJ Keller dbd9987d5e add options for simulator 2016-07-14 14:34:17 -04:00
AJ Keller 2832fcb6b2 saving 2016-07-14 14:34:17 -04:00
AJ Keller 61a2971275 fix 2016-07-14 14:34:17 -04:00
AJ Keller cc177e200d Saving 2016-07-14 14:34:17 -04:00
AJ Keller 12429398ca Working on daisy support 2016-07-14 14:34:17 -04:00
AJ Keller de3604f3b8 Add finalize protocol for daisy 2016-07-14 14:34:17 -04:00
AJ Keller 6f6ffe7ad8 get channel data array working for daisy 2016-07-14 14:34:17 -04:00
AJ Keller f4cd6b3a65 saving for the night 2016-07-14 14:34:17 -04:00
AJ Keller 443ee211ad Working on adding daisy 2016-07-14 14:34:17 -04:00
AJ Keller bfc0fe62a1 Fix for node 4.x.x 2016-07-14 14:34:17 -04:00
AJ Keller 4d7d4eb5d8 All tests passing 2016-07-14 14:34:17 -04:00
AJ Keller f948ec25f2 save 2016-07-14 14:34:17 -04:00
AJ Keller 78b830e5c0 saving... 2016-07-14 14:34:17 -04:00
AJ Keller 63a15cb950 Saving 2016-07-14 14:34:17 -04:00
AJ Keller f5bf4db9a0 saving 2016-07-14 14:34:17 -04:00
AJ Keller 117c4411da Saving... working on new parseing 2016-07-14 14:34:17 -04:00
AJ Keller 927f6c1596 small patch for auto tests 2016-07-14 14:34:17 -04:00
AJ Keller 81af1098ed wrote tests for routing packets based on end byte 2016-07-14 14:34:17 -04:00
AJ Keller a8fa5bab02 Refactored openBCISample 2016-07-14 14:34:17 -04:00
AJ Keller 982688008a New process bytes function working as expected with packets 2016-07-14 14:34:17 -04:00
AJ Keller cbbecc8b37 Add tests for new packet parser... testing underway 2016-07-14 14:34:17 -04:00
AJ Keller 4080fe0d1b Changed openBCIConstants to match ES6 syntax 2016-07-14 14:34:17 -04:00
AJ Keller 9e745331eb saving... 2016-07-14 14:34:17 -04:00
AJ Keller b1c8b81aa1 Saving... 2016-07-14 14:34:17 -04:00
AJ Keller de6e1ab353 Adding lots of automated tests... 2016-07-14 14:34:17 -04:00
AJ Keller cd108bd29a Saving.. 2016-07-14 14:34:17 -04:00
AJ Keller 79b46ecb53 Saving... 2016-07-14 14:34:17 -04:00
AJ Keller f8a47560b8 ENH ntp testing 2016-07-14 14:34:17 -04:00
AJ Keller 03ed89b516 ADD methods for time sync 2016-07-14 14:34:17 -04:00
AJ Keller bc436a7e1f Saving... 2016-07-14 14:34:17 -04:00
AJ Keller 2108ae2a75 ADD packet codes 2016-07-14 14:34:17 -04:00
AJ Keller 70689548a1 Saving 2016-07-14 14:34:17 -04:00
AJ Keller 701bc75a1f First sync with board 2016-07-14 14:34:17 -04:00
AJ Keller cce4f930ef NTP testing with firmware 2016-07-14 14:34:17 -04:00
AJ Keller 737f40e51e Saving for the night, stuff is starting to work though. 2016-07-14 14:34:17 -04:00
AJ Keller f00988716a ENH processBytes to support multiple packet types 2016-07-14 14:34:17 -04:00
Andy Heusser 7e7eb8f549 Merge pull request #68 from pushtheworldllc/dev
Validate packets before emitting raw data packets
2016-06-28 09:15:18 -04:00
AJ Keller 8383070639 Fix emit bad raw packets 2016-06-27 16:35:07 -04:00
AJ Keller b24d682e49 Bump version to match npm 2016-06-24 14:41:45 -04:00
Andy Heusser b36a7b3409 Merge pull request #67 from pushtheworldllc/dev
Fix constructor in readme.md Closes #66
2016-06-24 14:37:37 -04:00
AJ Keller cfa8f4bdc8 Fix constructor in readme.md Closes #66 2016-06-24 14:31:04 -04:00
AJ Keller ee66c49ff0 Update changelog.md
Forgot to update change log on merge
2016-06-21 21:21:14 -04:00
Andy Heusser abfb37a38e Merge pull request #65 from pushtheworldllc/dev-serialport-upgrade
Dev serialport upgrade
2016-06-21 17:14:40 -04:00
AJ Keller 48be1a01db ENH add more travis versions 2016-06-21 07:36:50 -04:00
AJ Keller 8bbc011ead ENH bump serialport to 3.0.0 2016-06-21 07:33:38 -04:00
Teon L Brooks cc839b3b32 Merge pull request #62 from pushtheworldllc/dev-sim-accel
Add accel data to simulator closes #61
2016-06-10 00:04:22 -04:00
AJ Keller e2cd5d1dd7 Add accel data to simulator closes #61 2016-06-09 21:44:22 -04:00
24 arquivos alterados com 13421 adições e 5910 exclusões
+1
Ver Arquivo
@@ -0,0 +1 @@
{"extends": ["standard"], "parser": "babel-eslint"}
+3
Ver Arquivo
@@ -33,6 +33,7 @@ public
# Test output files
myOutput.txt
hardwareVoltageOutputAll.txt
# Local npm builds for testing end in .tgz
*.tgz
@@ -40,3 +41,5 @@ myOutput.txt
# For git
*.orig
# Text editor temporary files
.*.sw* # vi/vim
+2 -1
Ver Arquivo
@@ -17,4 +17,5 @@ node_modules
.DS_Store
public
myOutput.txt
*.tgz
*.tgz
openBCISerialFormat
+15
Ver Arquivo
@@ -1,7 +1,22 @@
language: node_js
node_js:
- "4.0"
- "4.1"
- "4.2"
- "4.3"
- "4.4"
- "4.5"
- "4.6"
- "5.11.0"
- "6.0"
- "6.1"
- "6.2"
- "6.3"
- "6.4"
- "6.5"
- "6.6"
- "6.7"
- "6.8"
install:
- npm install --all
script:
+556 -198
Ver Arquivo
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+192 -8
Ver Arquivo
@@ -1,9 +1,194 @@
# 1.4.0
### New Features
* Three new initialization options: `simulatorFragmentation`, `simulatorBufferSize`, and `simulatorLatencyTimer`. Together, these enable a more _realistic_ serial port simulation, mimicking different potential user computer systems.
* New option `debug` gives a live dump of serial traffic on the console if enabled
* New API function `.isConnected()` to check if communications are active.
* New API function `.isStreaming()` to check if samples are coming from the board.
### Enhancements
* Implement and adapt semi-standard code style. Closes #83
* autoFindOpenBCIBoard now notices and uses the stock dongle on Linux
* 'synced' object now has `error` property, null on good syncs, error description on bad syncs.
### Breaking Changes
* The setting for simulatorInjectLineNoise has changed from `None` to `none`
* connect() will now fail if already connected
* The constructor will throw an error now if an invalid option is passed
* The `.connected` property has been removed, replaced by `.isConnected()`. Removed from docs.
* The `.streaming` property has been removed, replaced by `.isStreaming()`. Removed from docs.
* An error event will be emitted if sntp fails to initialize on construction
* The simulator will no longer communicate when disconnected
### Bug Fixes
* Fixed bug where early packet fragments were dropped after board reset
* Fixed bug where time sync replies that began a buffered chunk were ignored
* Fixed bug where simulator would output wrong version in its reset message
* Fixed bug where resources were not cleaned up if connect was called twice
* Fixed bug where serial data was written after disconnection
* Fixed bug where unexpected disconnection was not detected
* Fixed bug where promises could lead to out of order packet processing.
# 1.3.3
### New Features
* Add `timeOffsetMaster` to object emitted when bad time sync.
### Bug Fixes
* Fixed log statement on impedance setting function
* Remove event emitter with time sync on reject of sync clock full
# 1.3.2
### Enhancements
* Added master time offset `timeOffsetMaster` to `syncObj` which is a running average across sync attempts.
# 1.3.1
### Bug Fixes
* Fixed bug where `connected` and `streaming` were not set in constructor
# 1.3.0
### New Features
* Add dropped packet detection, new event `droppedPacket` can be added to get an array of dropped packet numbers in the case of the dropped packet event.
# 1.2.3
### Enhancements
* Add table of contents to read me
* Reduce size of repo by removing impedance test report
# 1.2.2
### Enhancements
* Upgrade serialport to 4.x
# 1.2.1
### Bug Fixes
* Fixed bug where set channel function allowed for channel 0 to be set. Cannot set system to channel 0; lower limit is 1.
# 1.2.0
### New Features
* Add tutorial/sample code for interfacing the module with lab streaming layer.
### Breaking Changes
* Fixed time synced accel to work OpenBCI_32bit_Library release candidate 5 and newer.
# 1.1.0
### New Features
* Add function `.time()` which should be used in time syncing
* Add function `.syncClocksFull()` which should be used for immediate consecutive time syncs
* Synced object can be emitted on `synced` event. Check `valid` property for if the sync was done
* Add detailed description of object returned on `synced` event to README.md
### Breaking Changes
* Changed option named `timeSync` to `sntpTimeSync`
* Removed function called `.sntpNow()` because it was replaced by `.time()`
### Bug Fixes
* Time sync working
* Module could not work with local time
# 1.0.1
### New Features
* Add time sync tutorial in `README.md`
### Bug Fixes
* Fixed bug in simulator that lead to samples being all zeros.
* Fixed time sync sent confirmation bug that led to bad time values.
# 1.0.0
The second major release for the OpenBCI Node.js SDK brings major changes, improvements and stability, on top of a push to increase automated test coverage.
### New Features
* NPM Module now called `openbci` instead of `openbci-sdk`
* Firmware version 2.0 support.
* Clock synchronization between OpenBCI board and this driver
* `.info` property which contains verified board information parsed from the OpenBCI's `softReset()` response.
* `eot` event that is emitted when a user sends a command that results in an EOT ("$$$") being sent from the board
* Daisy (16 channel) support
* Simulator overhaul, it completely mocks the board. Can now simulate board failure, where the board stops talking to the dongle. Can also mock a serial port failure.
* `error` and `close` events from serialport now emtted events users can subscribe to.
### Breaking Changes
* NPM package is not called `openbci-sdk` anymore, now called `openbci`
* Accelerometer data now goes into `.accelData` array instead of `.auxData` array.
* In openBCISample.js
* `parseRawPacket()` is now called `parseRawPacketStandard()`
* `ready` event only triggered after soft reset. `eot` event emitted in all other conditions resulting in the board sending EOT ("$$$")
* Must use camel case on the OpenBCISimulator object.
* Renamed constructor options for readability:
* `simulatorAlpha` to `simulatorInjectAlpha`
* `simulatorLineNoise` to `simulatorInjectLineNoise`
* `connect()` no longer rejects on `close` or `error` event from the serialport.
# 0.3.9
### Enhancements
* Add tests for parsing raw packets
### Bug Fixes
* Removed `got here` log from `.streamStart()`
* Validate stop byte before emitting `rawDataPacket`
# 0.3.8
### Bug Fixes
* Fixed readme.md
# 0.3.7
### New Features
* Upgrade dependencies
* Update Travis
### Bug Fixes
* `.numberOfChannels()` now uses the info object, which is set in the constructor and on the return message from `.softReset()`
* `.sampleRate()` now uses the info object, which is set in the constructor and on the return message from `.softReset()`
# 0.3.6
### New Features
* Simulator now has accelerometer data
# 0.3.5
### New Features
* SD card support! Now logging to an SD card is easier than ever.
* SD card support! Now logging to an SD card is easier than ever.
### Bug Fixes
* Sample rate does not return correct sample rate for custom rate on simulator. #58
@@ -18,7 +203,6 @@
* [https://github.com/OpenBCI/openbci-js-sdk/issues/44](#44)
# 0.3.3
### Bug Fixes
@@ -53,7 +237,7 @@
* OpenBCI Radio Test File
* Added Sntp npm module with helper functions
* Removed stopByte and startByte from sampleObjects
### Breaking Changes
* Changed simulator name to `OpenBCISimulator`
@@ -64,15 +248,15 @@
* NTP Time Synchronization
* Goertzel algorithm to get voltage for impedance calculation
### Bug fixes
* Impedance calculations
* Readme updates
* Serial buffer had the chance to become permanently unaligned, optimized and completely transformed and refactored the way bytes are processed.
* Changes to gain of channels not working correctly.
* Node 5 compatibility
* Node 5 compatibility
### Github Issues Addressed
* #25, #26, #27, #29, #30, #31, #33, #34
* #25, #26, #27, #29, #30, #31, #33, #34
+19
Ver Arquivo
@@ -0,0 +1,19 @@
{
"name": "timesync",
"version": "1.0.0",
"description": "Time sync example",
"main": "timeSync.js",
"scripts": {
"start": "node timeSync.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"time",
"sync"
],
"author": "AJ Keller",
"license": "MIT",
"dependencies": {
"openbci": "^1.3.1"
}
}
+88
Ver Arquivo
@@ -0,0 +1,88 @@
/**
* This is an example of time syncing every second for one minute. Used with a
* real board.
* To run:
* change directory to this file `cd examples/timeSync`
* do `npm install`
* then `npm start`
*/
var OpenBCIBoard = require('openbci').OpenBCIBoard;
var ourBoard = new OpenBCIBoard({});
var sampleRate = 250; // Default to 250, ALWAYS verify with a call to `.sampleRate()` after 'ready' event!
var timeSyncPossible = false;
ourBoard.autoFindOpenBCIBoard().then(portName => {
if (portName) {
/**
* Connect to the board with portName
* i.e. ourBoard.connect(portName).....
*/
// Call to connect
ourBoard.connect(portName).then(() => {
console.log(`connected`);
})
.catch(err => {
console.log(`connect: ${err}`);
});
} else {
/** Unable to auto find OpenBCI board */
}
});
var readyFunc = () => {
// Get the sample rate after 'ready'
sampleRate = ourBoard.sampleRate();
// Find out if you can even time sync, you must be using v2 and this is only accurate after a `.softReset()` call which is called internally on `.connect()`. We parse the `.softReset()` response for the presence of firmware version 2 properties.
timeSyncPossible = ourBoard.usingVersionTwoFirmware();
if (timeSyncPossible) {
ourBoard.streamStart()
.catch(err => {
console.log(`stream start: ${err}`);
});
} else {
killFunc();
}
};
var killFunc = () => {
ourBoard.disconnect()
.then(() => {
process.kill();
});
};
var sampleFunc = sample => {
// Resynchronize every every second
if (sample._count % (sampleRate * 1) === 0) {
ourBoard.syncClocksFull()
.then(syncObj => {
// Sync was successful
if (syncObj.valid) {
// Log the object to check it out!
console.log(`timeOffset`, syncObj.timeOffsetMaster);
} else {
// Retry it
console.log(`Was not able to sync... retry!`);
}
});
}
if (sample.timeStamp) { // true after the first successful sync
if (sample.timeStamp < 10 * 60 * 60 * 1000) { // Less than 10 hours
console.log(`Bad time sync ${sample.timeStamp}`);
}
}
// Stop after one minute
if (sample._count > sampleRate * 60) {
killFunc();
}
};
// Subscribe to your functions
ourBoard.on('ready', readyFunc);
ourBoard.on('sample', sampleFunc);
Ver Arquivo
Arquivo binário não exibido.
+2293 -1319
Ver Arquivo
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+1109 -921
Ver Arquivo
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+1175 -462
Ver Arquivo
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+420 -183
Ver Arquivo
@@ -1,5 +1,4 @@
'use strict';
var EventEmitter = require('events').EventEmitter;
var util = require('util');
var stream = require('stream');
@@ -8,215 +7,453 @@ var openBCISample = require('./openBCISample');
var k = openBCISample.k;
var now = require('performance-now');
function OpenBCISimulatorFactory () {
var factory = this;
function OpenBCISimulatorFactory() {
var factory = this;
var _options = {
accel: true,
alpha: true,
boardFailure: false,
daisy: false,
drift: 0,
firmwareVersion: [k.OBCIFirmwareV1, k.OBCIFirmwareV2],
fragmentation: [k.OBCISimulatorFragmentationNone, k.OBCISimulatorFragmentationRandom, k.OBCISimulatorFragmentationFullBuffers, k.OBCISimulatorFragmentationOneByOne],
latencyTime: 16,
bufferSize: 4096,
lineNoise: [k.OBCISimulatorLineNoiseHz60, k.OBCISimulatorLineNoiseHz50, k.OBCISimulatorLineNoiseNone],
sampleRate: 250,
serialPortFailure: false,
verbose: false
};
function OpenBCISimulator (portName, options) {
options = (typeof options !== 'function') && options || {};
var opts = {};
stream.Stream.call(this);
var _options = {
samplerate: 250,
daisy: false,
verbose: false,
alpha: true,
lineNoise: '60Hz'
};
/** Configuring Options */
var o;
for (o in _options) {
var userValue = options[o];
delete options[o];
if (typeof _options[o] === 'object') {
// an array specifying a list of choices
// if the choice is not in the list, the first one is defaulted to
if (_options[o].indexOf(userValue) !== -1) {
opts[o] = userValue;
} else {
opts[o] = _options[o][0];
}
} else {
// anything else takes the user value if provided, otherwise is a default
function OpenBCISimulator(portName, options) {
options = (typeof options !== 'function') && options || {};
var opts = {};
stream.Stream.call(this);
/** Configuring Options */
opts.sampleRate = options.sampleRate || options.samplerate || _options.samplerate;
opts.daisy = options.daisy || _options.daisy;
opts.lineNoise = options.lineNoise || options.linenoise || _options.lineNoise;
opts.alpha = options.alpha || _options.alpha;
opts.verbose = options.verbose || _options.verbose;
this.options = opts;
// Bools
this.connected = false;
this.sd = {
active:false,
startTime: 0
};
this.streaming = false;
// Buffers
this.buffer = new Buffer(500);
// Numbers
this.sampleNumber = -1; // So the first sample is 0
// Objects
this.time = {
current: 0,
start: now(),
loop: null,
ntp0: 0,
ntp1: 0,
ntp2: 0,
ntp3: 0
};
console.log('Simulator started at time: ' + this.time.start);
console.log('Time board has been running: ' + (now() - this.time.start));
// Strings
this.portName = portName || k.OBCISimulatorPortName;
// Call 'open'
setTimeout(() => {
console.log('Port name: ' + portName);
if (portName === k.OBCISimulatorPortName) {
this.emit('open');
this.connected = true;
} else {
var err = new Error('Serialport not open.');
this.emit('error',err);
}
}, 200);
if (userValue !== undefined) {
opts[o] = userValue;
} else {
opts[o] = _options[o];
}
}
}
// This allows us to use the emitter class freely outside of the module
util.inherits(OpenBCISimulator, stream.Stream);
for (o in options) throw new Error('"' + o + '" is not a valid option');
OpenBCISimulator.prototype.flush = function() {
this.buffer.fill(0);
//if (this.options.verbose) console.log('flushed');
this.options = opts;
// Bools
this.connected = false;
this.sd = {
active: false,
startTime: 0
};
this.streaming = false;
this.synced = false;
this.sendSyncSetPacket = false;
// Buffers
this.outputBuffer = new Buffer(this.options.bufferSize);
this.outputBuffered = 0;
// Numbers
this.channelNumber = 1;
this.hostChannelNumber = this.channelNumber;
this.pollTime = 80;
this.sampleNumber = -1; // So the first sample is 0
// Objects
this.sampleGenerator = openBCISample.randomSample(k.OBCINumberOfChannelsDefault, this.options.sampleRate, this.options.alpha, this.options.lineNoise);
this.time = {
current: 0,
start: now(),
loop: null
};
// Strings
this.portName = portName || k.OBCISimulatorPortName;
OpenBCISimulator.prototype.write = function(data,callback) {
// Call 'open'
if (this.options.verbose) console.log(`Port name: ${portName}`);
setTimeout(() => {
this.connected = true;
this.emit('open');
}, 200);
}
switch (data[0]) {
case k.OBCIStreamStart:
if (!this.stream) this._startStream();
this.streaming = true;
break;
case k.OBCIStreamStop:
if (this.stream) clearInterval(this.stream); // Stops the stream
this.streaming = false;
break;
case k.OBCIMiscSoftReset:
if (this.stream) clearInterval(this.stream);
this.streaming = false;
this.emit('data', new Buffer('OpenBCI Board Simulator\nPush The World\nFirmware: v2$$$'));
break;
case k.OBCISDLogForHour1:
case k.OBCISDLogForHour2:
case k.OBCISDLogForHour4:
case k.OBCISDLogForHour12:
case k.OBCISDLogForHour24:
case k.OBCISDLogForMin5:
case k.OBCISDLogForMin15:
case k.OBCISDLogForMin30:
case k.OBCISDLogForSec14:
// If we are not streaming, then do verbose output
if (!this.streaming) {
this.emit('data', new Buffer('Wiring is correct and a card is present.\nCorresponding SD file OBCI_69.TXT\n$$$'));
}
this.sd.active = true;
this.sd.startTime = now();
break;
case k.OBCISDLogStop:
if (!this.streaming) {
if (this.SDLogActive) {
this.emit('data', new Buffer('Total Elapsed Time: ' + (now() - this.sd.startTime) + ' ms\n'));
this.emit('data', new Buffer('Max write time: ' + (Math.random()*500) + ' us\n'));
this.emit('data', new Buffer('Min write time: ' + (Math.random()*200) + ' us\n'));
this.emit('data', new Buffer('Overruns: 0\n$$$'));
} else {
this.emit('data', new Buffer('No open file to close\n$$$'));
}
}
this.SDLogActive = false;
break;
case k.OBCISyncClockStart:
setTimeout(() => {
if (this.options.verbose) console.log('Recieved sync command');
this._syncStart();
}, 10);
break;
case k.OBCISyncClockServerData:
this.time.ntp3 = this.time.current;
this._syncUp(data.slice(1));
break;
default:
break;
// This allows us to use the emitter class freely outside of the module
// TODO: upgrade from old-style streams to stream.Duplex or stream.Transform
util.inherits(OpenBCISimulator, stream.Stream);
OpenBCISimulator.prototype.flush = function () {
this.outputBuffered = 0;
clearTimeout(this.outputLoopHandle);
this.outputLoopHandle = null;
};
OpenBCISimulator.prototype.isOpen = function () {
return this.connected;
};
// output only size bytes of the output buffer
OpenBCISimulator.prototype._partialDrain = function (size) {
if (!this.connected) throw new Error('not connected');
if (size > this.outputBuffered) size = this.outputBuffered;
// buffer is copied because presently openBCIBoard.js reuses it
var outBuffer = new Buffer(this.outputBuffer.slice(0, size));
this.outputBuffer.copy(this.outputBuffer, 0, size, this.outputBuffered);
this.outputBuffered -= size;
this.emit('data', outBuffer);
};
// queue some data for output and send it out depending on options.fragmentation
OpenBCISimulator.prototype._output = function (dataBuffer) {
// drain full buffers until there is no overflow
while (this.outputBuffered + dataBuffer.length > this.outputBuffer.length) {
var len = dataBuffer.copy(this.outputBuffer, this.outputBuffered);
dataBuffer = dataBuffer.slice(len);
this.outputBuffered += len;
this._partialDrain(this.outputBuffered);
this.flush();
}
dataBuffer.copy(this.outputBuffer, this.outputBuffered);
this.outputBuffered += dataBuffer.length;
if (!this.outputLoopHandle) {
var latencyTime = this.options.latencyTime;
if (this.options.fragmentation === k.OBCISimulatorFragmentationOneByOne ||
this.options.fragmentation === k.OBCISimulatorFragmentationNone) {
// no need to wait for latencyTime
// note that this is the only difference between 'none' and 'fullBuffers'
latencyTime = 0;
}
var outputLoop = () => {
var size;
switch (this.options.fragmentation) {
case k.OBCISimulatorFragmentationRandom:
if (Math.random() < 0.5) {
// randomly picked to send out a fragment
size = Math.ceil(Math.random() * Math.max(this.outputBuffered, 62));
break;
} // else, randomly picked to send a complete buffer in next block
/* falls through */
case k.OBCISimulatorFragmentationFullBuffers:
case k.OBCISimulatorFragmentationNone:
case false:
size = this.outputBuffered;
break;
case k.OBCISimulatorFragmentationOneByOne:
size = 1;
break;
}
/** Handle Callback */
if (this.connected) {
callback(null,'Success!');
this._partialDrain(size);
if (this.outputBuffered) {
this.outputLoopHandle = setTimeout(outputLoop, latencyTime);
} else {
this.outputLoopHandle = null;
}
};
};
if (latencyTime === 0) {
outputLoop();
} else {
this.outputLoopHandle = setTimeout(outputLoop, latencyTime);
}
}
};
OpenBCISimulator.prototype.drain = function(callback) {
callback();
//if (this.options.verbose) console.log('drain');
};
OpenBCISimulator.prototype.write = function (data, callback) {
if (!this.connected) {
if (callback) callback('Not connected');
else throw new Error('Not connected!');
return;
}
OpenBCISimulator.prototype.close = function(callback) {
if (this.connected) {
this.emit('close');
// TODO: this function assumes a type of Buffer for radio, and a type of String otherwise
// FIX THIS it makes it unusable outside the api code
switch (data[0]) {
case k.OBCIRadioKey:
this._processPrivateRadioMessage(data);
break;
case k.OBCIStreamStart:
if (!this.stream) this._startStream();
this.streaming = true;
break;
case k.OBCIStreamStop:
if (this.stream) clearInterval(this.stream); // Stops the stream
this.streaming = false;
break;
case k.OBCIMiscSoftReset:
if (this.stream) clearInterval(this.stream);
this.streaming = false;
this._output(new Buffer(`OpenBCI V3 Simulator On Board ADS1299 Device ID: 0x12345 ${this.options.daisy ? `On Daisy ADS1299 Device ID: 0xFFFFF\n` : ``} LIS3DH Device ID: 0x38422 ${this.options.firmwareVersion === k.OBCIFirmwareV2 ? `Firmware: v2.0.0\n` : ``}$$$`));
break;
case k.OBCISDLogForHour1:
case k.OBCISDLogForHour2:
case k.OBCISDLogForHour4:
case k.OBCISDLogForHour12:
case k.OBCISDLogForHour24:
case k.OBCISDLogForMin5:
case k.OBCISDLogForMin15:
case k.OBCISDLogForMin30:
case k.OBCISDLogForSec14:
// If we are not streaming, then do verbose output
if (!this.streaming) {
this._output(new Buffer('Wiring is correct and a card is present.\nCorresponding SD file OBCI_69.TXT\n$$$'));
}
this.connected = false;
//if (this.options.verbose) console.log('close');
callback();
this.sd.active = true;
this.sd.startTime = now();
break;
case k.OBCISDLogStop:
if (!this.streaming) {
if (this.SDLogActive) {
this._output(new Buffer(`Total Elapsed Time: ${now() - this.sd.startTime} ms`));
this._output(new Buffer(`Max write time: ${Math.random() * 500} us`));
this._output(new Buffer(`Min write time: ${Math.random() * 200} us`));
this._output(new Buffer(`Overruns: 0`));
this._printEOT();
} else {
this._output(new Buffer('No open file to close\n'));
this._printEOT();
}
}
this.SDLogActive = false;
break;
case k.OBCISyncTimeSet:
if (this.options.firmwareVersion === k.OBCIFirmwareV2) {
this.synced = true;
setTimeout(() => {
this._output(new Buffer(k.OBCISyncTimeSent));
this._syncUp();
}, 10);
}
break;
default:
break;
}
/** Handle Callback */
if (callback) {
callback(null, 'Success!');
}
};
OpenBCISimulator.prototype.drain = function (callback) {
if (callback) callback();
};
OpenBCISimulator.prototype.close = function (callback) {
if (this.connected) {
this.flush();
if (this.stream) clearInterval(this.stream);
this.connected = false;
this.emit('close');
if (callback) callback();
} else {
if (callback) callback('not connected');
}
};
OpenBCISimulator.prototype._startStream = function () {
var intervalInMS = 1000 / this.options.sampleRate;
if (intervalInMS < 2) intervalInMS = 2;
var getNewPacket = sampNumber => {
if (this.options.accel) {
if (this.synced) {
if (this.sendSyncSetPacket) {
this.sendSyncSetPacket = false;
return openBCISample.convertSampleToPacketAccelTimeSyncSet(this.sampleGenerator(sampNumber), now().toFixed(0));
} else {
return openBCISample.convertSampleToPacketAccelTimeSynced(this.sampleGenerator(sampNumber), now().toFixed(0));
}
} else {
return openBCISample.convertSampleToPacketStandard(this.sampleGenerator(sampNumber));
}
} else {
if (this.synced) {
if (this.sendSyncSetPacket) {
this.sendSyncSetPacket = false;
return openBCISample.convertSampleToPacketRawAuxTimeSyncSet(this.sampleGenerator(sampNumber), now().toFixed(0), new Buffer([0, 0, 0, 0, 0, 0]));
} else {
return openBCISample.convertSampleToPacketRawAuxTimeSynced(this.sampleGenerator(sampNumber), now().toFixed(0), new Buffer([0, 0, 0, 0, 0, 0]));
}
} else {
return openBCISample.convertSampleToPacketRawAux(this.sampleGenerator(sampNumber), new Buffer([0, 0, 0, 0, 0, 0]));
}
}
};
OpenBCISimulator.prototype._startStream = function() {
var intervalInMS = 1000 / this.options.sampleRate;
this.stream = setInterval(() => {
this._output(getNewPacket(this.sampleNumber));
this.sampleNumber++;
}, intervalInMS);
};
if (intervalInMS < 2) intervalInMS = 2;
OpenBCISimulator.prototype._syncUp = function () {
setTimeout(() => {
this.sendSyncSetPacket = true;
}, 12); // 3 packets later
};
var generateSample = openBCISample.randomSample(k.OBCINumberOfChannelsDefault, k.OBCISampleRate250, this.options.alpha, this.options.lineNoise);
OpenBCISimulator.prototype._printEOT = function () {
this._output(new Buffer('$$$'));
};
var getNewPacket = sampNumber => {
return openBCISample.convertSampleToPacket(generateSample(sampNumber));
};
OpenBCISimulator.prototype._printFailure = function () {
this._output(new Buffer('Failure: '));
};
this.stream = setInterval(() => {
this.emit('data', getNewPacket(this.sampleNumber));
this.sampleNumber++;
}, intervalInMS);
};
OpenBCISimulator.prototype._printSuccess = function () {
this._output(new Buffer('Success: '));
};
OpenBCISimulator.prototype._syncStart = function() {
OpenBCISimulator.prototype._printValidatedCommsTimeout = function () {
this._printFailure();
this._output(new Buffer('Communications timeout - Device failed to poll Host'));
this._printEOT();
};
this.time.ntp0 = now();
var buffer = new Buffer('$a$' + this.time.ntp0);
this.emit('data',buffer);
};
OpenBCISimulator.prototype._syncUp = function(data) {
// get the first number
console.log(data.length);
var halfwayPoint = (data.length / 2);
this.time.ntp1 = parseFloat(data.slice(0,halfwayPoint-1));
this.time.ntp2 = parseFloat(data.slice(halfwayPoint));
console.log('ntp1: ' + this.time.ntp1 + ' ntp2: ' + this.time.ntp2);
var timeSpentOnNetwork = this.time.ntp3 - this.time.ntp0 - (this.time.ntp2 - this.time.ntp1);
var transferTime = timeSpentOnNetwork / 2;
var trueTime = this.time.ntp2 + transferTime;
var delta = trueTime - this.time.ntp3;
console.log('Delta: ' + delta);
this.time.start += delta;
this.emit('data','Synced!' + '$$$');
};
factory.OpenBCISimulator = OpenBCISimulator;
OpenBCISimulator.prototype._processPrivateRadioMessage = function (dataBuffer) {
switch (dataBuffer[1]) {
case k.OBCIRadioCmdChannelGet:
if (this.options.firmwareVersion === k.OBCIFirmwareV2) {
if (!this.options.boardFailure) {
this._printSuccess();
this._output(new Buffer(`Host and Device on Channel Number ${this.channelNumber}`));
this._output(new Buffer([this.channelNumber]));
this._printEOT();
} else if (!this.serialPortFailure) {
this._printFailure();
this._output(new Buffer(`Host on Channel Number ${this.channelNumber}`));
this._output(new Buffer([this.channelNumber]));
this._printEOT();
}
}
break;
case k.OBCIRadioCmdChannelSet:
if (this.options.firmwareVersion === k.OBCIFirmwareV2) {
if (!this.options.boardFailure) {
if (dataBuffer[2] <= k.OBCIRadioChannelMax) {
this.channelNumber = dataBuffer[2];
this.hostChannelNumber = this.channelNumber;
this._printSuccess();
this._output(new Buffer(`Channel Number ${this.channelNumber}`));
this._output(new Buffer([this.channelNumber]));
this._printEOT();
} else {
this._printFailure();
this._output(new Buffer('Verify channel number is less than 25'));
this._printEOT();
}
} else if (!this.serialPortFailure) {
this._printValidatedCommsTimeout();
}
}
break;
case k.OBCIRadioCmdChannelSetOverride:
if (this.options.firmwareVersion === k.OBCIFirmwareV2) {
if (dataBuffer[2] <= k.OBCIRadioChannelMax) {
if (dataBuffer[2] === this.channelNumber) {
this.options.boardFailure = false;
} else {
this.options.boardFailure = true;
}
this.hostChannelNumber = dataBuffer[2];
this._printSuccess();
this._output(new Buffer(`Host override - Channel Number ${this.hostChannelNumber}`));
this._output(new Buffer([this.hostChannelNumber]));
this._printEOT();
} else {
this._printFailure();
this._output(new Buffer('Verify channel number is less than 25'));
this._printEOT();
}
}
break;
case k.OBCIRadioCmdPollTimeGet:
if (this.options.firmwareVersion === k.OBCIFirmwareV2) {
if (!this.options.boardFailure) {
this._printSuccess();
this._output(new Buffer(`Poll Time ${this.pollTime}`));
this._output(new Buffer([this.pollTime]));
this._printEOT();
} else {
this._printValidatedCommsTimeout();
}
}
break;
case k.OBCIRadioCmdPollTimeSet:
if (this.options.firmwareVersion === k.OBCIFirmwareV2) {
if (!this.options.boardFailure) {
this.pollTime = dataBuffer[2];
this._printSuccess();
this._output(new Buffer(`Poll Time ${this.pollTime}`));
this._output(new Buffer([this.pollTime]));
this._printEOT();
} else {
this._printValidatedCommsTimeout();
}
}
break;
case k.OBCIRadioCmdBaudRateSetDefault:
if (this.options.firmwareVersion === k.OBCIFirmwareV2) {
this._printSuccess();
this._output(new Buffer('Switch your baud rate to 115200'));
this._output(new Buffer([0x24, 0x24, 0x24, 0xFF])); // The board really does this
}
break;
case k.OBCIRadioCmdBaudRateSetFast:
if (this.options.firmwareVersion === k.OBCIFirmwareV2) {
this._printSuccess();
this._output(new Buffer('Switch your baud rate to 230400'));
this._output(new Buffer([0x24, 0x24, 0x24, 0xFF])); // The board really does this
}
break;
case k.OBCIRadioCmdSystemStatus:
if (this.options.firmwareVersion === k.OBCIFirmwareV2) {
if (!this.options.boardFailure) {
this._printSuccess();
this._output(new Buffer('System is Up'));
this._printEOT();
} else {
this._printFailure();
this._output(new Buffer('System is Down'));
this._printEOT();
}
}
break;
default:
break;
}
};
factory.OpenBCISimulator = OpenBCISimulator;
}
util.inherits(OpenBCISimulatorFactory, EventEmitter);
+30 -11
Ver Arquivo
@@ -1,11 +1,11 @@
{
"name": "openbci-sdk",
"version": "0.3.5",
"name": "openbci",
"version": "1.4.0",
"description": "The official Node.js SDK for the OpenBCI Biosensor Board.",
"main": "openBCIBoard",
"scripts": {
"start": "node index",
"test": "mocha test",
"test": "semistandard | snazzy && mocha test",
"test-cov": "istanbul cover ./node_modules/mocha/bin/_mocha -- -R spec && codecov"
},
"keywords": [
@@ -15,33 +15,52 @@
"author": "AJ Keller <aj@pushtheworld.us> (www.openbci.com)",
"license": "MIT",
"dependencies": {
"buffer-equal": "^1.0.0",
"gaussian": "^1.0.0",
"istanbul": "^0.4.2",
"mathjs": "^3.3.0",
"performance-now": "^0.2.0",
"serialport": "~2.1.0",
"sntp": "^2.0.0"
"serialport": "4.0.1",
"sntp": "^2.0.0",
"streamsearch": "^0.1.2"
},
"directories": {
"test": "test"
},
"devDependencies": {
"bluebird": "3.4.6",
"chai": "^3.4.1",
"chai-as-promised": "^5.2.0",
"codecov": "^1.0.1",
"mocha": "^2.3.4",
"istanbul": "^0.4.4",
"mocha": "^3.0.2",
"sandboxed-module": "^2.0.3",
"semistandard": "^9.0.0",
"sinon": "^1.17.2",
"sinon-chai": "^2.8.0"
"sinon-chai": "^2.8.0",
"snazzy": "^5.0.0"
},
"repository": {
"type": "git",
"url": "git+https://github.com/openbci/openbci-js-sdk.git"
"url": "git+https://github.com/openbci/openbci_nodejs.git"
},
"bugs": {
"url": "https://github.com/openbci/openbci-js-sdk/issues"
"url": "https://github.com/openbci/openbci_nodejs/issues"
},
"homepage": "https://github.com/openbci/openbci-js-sdk#readme",
"homepage": "https://github.com/openbci/openbci_nodejs#readme",
"engines": {
"node": ">=4.0.0"
},
"semistandard": {
"globals": [
"describe",
"context",
"before",
"beforeEach",
"after",
"afterEach",
"it",
"expect",
"should"
]
}
}
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+1213 -296
Ver Arquivo
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+142
Ver Arquivo
@@ -0,0 +1,142 @@
var timingEventsAsPromises = require('./timingEventsAsPromises');
exports.BluebirdPromise = require('bluebird');
exports.PromiseIgnored = global.Promise;
// Enable bluebird for all promise usage during tests only
// Fails tests for issues bluebird finds
// Exports a function to list all promises (getPendingPromises)
// Exports a function to verify no promises pending within a timeout (noPendingPromises)
exports.BluebirdPromise.config({
// TODO: wForgottenReturn is disabled because timingEventsAsPromises triggers it; find a workaround
warnings: { wForgottenReturn: false },
longStackTraces: true,
monitoring: true,
cancellation: true
});
// nextTick conveniently not instrumented by timingEventsAsPromises
exports.BluebirdPromise.setScheduler(process.nextTick);
// unhandled rejections become test failures
process.on('unhandledRejection', (reason, promise) => {
if (!(reason instanceof Error)) {
reason = new Error('unhandled promise rejection: ' + reason);
} else {
reason.message = 'unhandled promise rejection: ' + reason.message;
}
process.nextTick(() => { throw reason; });
});
// // warnings become test failures
// process.on('warning', (warning) => {
// var error = new Error(warning);
// process.nextTick(() => { throw error; });
// });
// provide access to all currently pending promises
var pendingPromises = {};
var promiseId = 0;
var nested = 0;
function promiseCreationHandler (promise) {
// promise created already resolved; ignore
if (!promise.isPending()) return;
// need to create another promise to get access to the extended stack trace
// nested detects if we are inside our own dummy promise
++nested;
if (nested === 1) {
// not the dummy promise
promise.___id = ++promiseId;
// store promise details
var error = new Error('Promise ' + promise.___id + ' is still pending');
var entry = {
promise: promise,
id: promise.___id,
error: error
};
pendingPromises[promise.___id] = entry;
// extract stack trace by rejecting an error; bluebird fills in expanded stack
exports.BluebirdPromise.reject(error).catch(error => {
entry.error = error;
entry.stack = error.stack;
});
} else {
promise.___nested = nested;
}
--nested;
}
process.on('promiseCreated', promiseCreationHandler);
function promiseDoneHandler (promise) {
if (promise.___nested) return;
delete pendingPromises[promise.___id];
}
process.on('promiseFulfilled', promiseDoneHandler);
process.on('promiseRejected', promiseDoneHandler);
process.on('promiseResolved', promiseDoneHandler);
process.on('promiseCancelled', promiseDoneHandler);
exports.getPendingPromises = function () {
var ret = [];
for (var promise in pendingPromises) {
ret.push(pendingPromises[promise]);
}
return ret;
};
exports.noPendingPromises = function (milliseconds) {
if (!milliseconds) milliseconds = 0;
return new exports.PromiseIgnored((resolve, reject) => {
function waited100 () {
var promises = exports.getPendingPromises();
if (promises.length === 0) {
return resolve();
}
if (milliseconds > 0) {
milliseconds -= 100;
return timingEventsAsPromises.setTimeoutIgnored(waited100, 100);
}
// timed out, but promises remaining: cancel all
console.log(promises.length + ' promises still pending');
promises.forEach(promise => {
promise.promise.cancel();
});
// report one
reject(promises[0].error);
}
timingEventsAsPromises.setTimeoutIgnored(waited100, 0);
});
};
// now instrument the Promise object itself to always use a simplified version of bluebird
// bluebird is composed inside a bare-bones Promise object providing only the official calls
global.Promise = function (handler) {
this._promise = new exports.BluebirdPromise(handler);
};
// compose class methods
['all', 'race', 'reject', 'resolve'].forEach(classMethod => {
global.Promise[classMethod] = function () {
return exports.BluebirdPromise[classMethod].apply(exports.BluebirdPromise, [].slice.call(arguments));
};
Object.defineProperty(global.Promise[classMethod], 'name', { value: 'Promise.' + classMethod });
});
// compose object methods
['then', 'catch'].forEach(objectMethod => {
global.Promise.prototype[objectMethod] = function () {
return this._promise[objectMethod].apply(this._promise, [].slice.call(arguments));
};
Object.defineProperty(global.Promise.prototype[objectMethod], 'name', { value: 'Promise.' + objectMethod });
});
+608
Ver Arquivo
@@ -0,0 +1,608 @@
'use strict';
var bluebirdChecks = require('./bluebirdChecks');
var chai = require('chai');
var should = chai.should(); // eslint-disable-line no-unused-vars
var openBCIBoard = require('../openBCIBoard');
var openBCISample = openBCIBoard.OpenBCISample;
var k = openBCISample.k;
var chaiAsPromised = require('chai-as-promised');
var sinonChai = require('sinon-chai');
chai.use(chaiAsPromised);
chai.use(sinonChai);
describe('#impedanceTesting', function () {
var ourBoard;
this.timeout(20000);
before(function (done) {
ourBoard = new openBCIBoard.OpenBCIBoard({
verbose: true,
simulatorFragmentation: k.OBCISimulatorFragmentationRandom
});
var useSim = () => {
return ourBoard.simulatorEnable().then(() => {
return ourBoard.connect(k.OBCISimulatorPortName);
});
};
ourBoard.autoFindOpenBCIBoard()
.then(portName => {
return ourBoard.connect(portName);
})
.catch(() => {
return useSim();
})
.then(() => {
console.log('connected');
})
.catch(err => {
console.log('Error: ' + err);
});
ourBoard.once('ready', () => {
ourBoard.streamStart()
.then(() => {
setTimeout(() => {
done();
}, 100); // give some time for the stream command to be sent
})
.catch(err => {
console.log(err);
done(err);
});
});
});
after(done => {
if (ourBoard.isConnected()) {
ourBoard.disconnect()
.then(() => {
done();
})
.catch(err => {
done(err);
});
} else {
done();
}
});
after(() => bluebirdChecks.noPendingPromises());
describe('#impedanceTestAllChannels', function () {
var impedanceArray = [];
before(function (done) {
ourBoard.once('impedanceArray', arr => {
impedanceArray = arr;
console.log(impedanceArray);
done();
});
ourBoard.impedanceTestAllChannels();
});
describe('#channel1', function () {
it('has valid channel number', function () {
impedanceArray[0].channel.should.be.equal(1);
});
describe('#inputP', function () {
it('got raw impedance value', function () {
impedanceArray[0].P.should.have.property('raw').above(-1);
});
it("text is not 'init'", function () {
impedanceArray[0].P.should.have.property('text').not.be.equal(k.OBCIImpedanceTextInit);
});
});
describe('#inputN', function () {
it('got raw impedance value', function () {
impedanceArray[0].N.should.have.property('raw').above(-1);
});
it("text is not 'init'", function () {
impedanceArray[0].N.should.have.property('text').not.be.equal(k.OBCIImpedanceTextInit);
});
});
});
describe('#channel2', function () {
it('has valid channel number', function () {
impedanceArray[1].channel.should.be.equal(2);
});
describe('#inputP', function () {
it('got raw impedance value', function () {
impedanceArray[1].P.should.have.property('raw').above(-1);
});
it("text is not 'init'", function () {
impedanceArray[1].P.should.have.property('text').not.be.equal(k.OBCIImpedanceTextInit);
});
});
describe('#inputN', function () {
it('got raw impedance value', function () {
impedanceArray[1].N.should.have.property('raw').above(-1);
});
it("text is not 'init'", function () {
impedanceArray[1].N.should.have.property('text').not.be.equal(k.OBCIImpedanceTextInit);
});
});
});
describe('#channel3', function () {
it('has valid channel number', function () {
impedanceArray[2].channel.should.be.equal(3);
});
describe('#inputP', function () {
it('got raw impedance value', function () {
impedanceArray[2].P.should.have.property('raw').above(-1);
});
it("text is not 'init'", function () {
impedanceArray[2].P.should.have.property('text').not.be.equal(k.OBCIImpedanceTextInit);
});
});
describe('#inputN', function () {
it('got raw impedance value', function () {
impedanceArray[2].N.should.have.property('raw').above(-1);
});
it("text is not 'init'", function () {
impedanceArray[2].N.should.have.property('text').not.be.equal(k.OBCIImpedanceTextInit);
});
});
});
describe('#channel4', function () {
it('has valid channel number', function () {
impedanceArray[3].channel.should.be.equal(4);
});
describe('#inputP', function () {
it('got raw impedance value', function () {
impedanceArray[3].P.should.have.property('raw').above(-1);
});
it("text is not 'init'", function () {
impedanceArray[3].P.should.have.property('text').not.be.equal(k.OBCIImpedanceTextInit);
});
});
describe('#inputN', function () {
it('got raw impedance value', function () {
impedanceArray[3].N.should.have.property('raw').above(-1);
});
it("text is not 'init'", function () {
impedanceArray[3].N.should.have.property('text').not.be.equal(k.OBCIImpedanceTextInit);
});
});
});
describe('#channel5', function () {
it('has valid channel number', function () {
impedanceArray[4].channel.should.be.equal(5);
});
describe('#inputP', function () {
it('got raw impedance value', function () {
impedanceArray[4].P.should.have.property('raw').above(-1);
});
it("text is not 'init'", function () {
impedanceArray[4].P.should.have.property('text').not.be.equal(k.OBCIImpedanceTextInit);
});
});
describe('#inputN', function () {
it('got raw impedance value', function () {
impedanceArray[4].N.should.have.property('raw').above(-1);
});
it("text is not 'init'", function () {
impedanceArray[4].N.should.have.property('text').not.be.equal(k.OBCIImpedanceTextInit);
});
});
});
describe('#channel6', function () {
it('has valid channel number', function () {
impedanceArray[5].channel.should.be.equal(6);
});
describe('#inputP', function () {
it('got raw impedance value', function () {
impedanceArray[5].P.should.have.property('raw').above(-1);
});
it("text is not 'init'", function () {
impedanceArray[5].P.should.have.property('text').not.be.equal(k.OBCIImpedanceTextInit);
});
});
describe('#inputN', function () {
it('got raw impedance value', function () {
impedanceArray[5].N.should.have.property('raw').above(-1);
});
it("text is not 'init'", function () {
impedanceArray[5].N.should.have.property('text').not.be.equal(k.OBCIImpedanceTextInit);
});
});
});
describe('#channel7', function () {
it('has valid channel number', function () {
impedanceArray[6].channel.should.be.equal(7);
});
describe('#inputP', function () {
it('got raw impedance value', function () {
impedanceArray[6].P.should.have.property('raw').above(-1);
});
it("text is not 'init'", function () {
impedanceArray[6].P.should.have.property('text').not.be.equal(k.OBCIImpedanceTextInit);
});
});
describe('#inputN', function () {
it('got raw impedance value', function () {
impedanceArray[6].N.should.have.property('raw').above(-1);
});
it("text is not 'init'", function () {
impedanceArray[6].N.should.have.property('text').not.be.equal(k.OBCIImpedanceTextInit);
});
});
});
describe('#channel8', function () {
it('has valid channel number', function () {
impedanceArray[7].channel.should.be.equal(8);
});
describe('#inputP', function () {
it('got raw impedance value', function () {
impedanceArray[7].P.should.have.property('raw').above(-1);
});
it("text is not 'init'", function () {
impedanceArray[7].P.should.have.property('text').not.be.equal(k.OBCIImpedanceTextInit);
});
});
describe('#inputN', function () {
it('got raw impedance value', function () {
impedanceArray[7].N.should.have.property('raw').above(-1);
});
it("text is not 'init'", function () {
impedanceArray[7].N.should.have.property('text').not.be.equal(k.OBCIImpedanceTextInit);
});
});
});
});
describe('#impedanceTestChannelsRejects', function () {
it('rejects when it does not get an array', function (done) {
ourBoard.impedanceTestChannels('taco').should.be.rejected.and.notify(done);
});
it('rejects when it array length does not match number of channels', function (done) {
ourBoard.impedanceTestChannels(['-', 'N', 'n', 'p', 'P', 'p', 'b']).should.be.rejected.and.notify(done);
});
});
describe('#impedanceTestChannels', function () {
var impedanceArray = [];
before(function (done) {
ourBoard.once('impedanceArray', arr => {
impedanceArray = arr;
done();
});
ourBoard.impedanceArray[0] = openBCISample.impedanceObject(1);
ourBoard.impedanceTestChannels(['-', 'N', 'n', 'p', 'P', 'p', 'b', 'B']).catch(err => done(err));
});
describe('#channel1', function () {
it('has valid channel number', function () {
impedanceArray[0].channel.should.be.equal(1);
});
describe('#inputP', function () {
it('got raw impedance value', function () {
impedanceArray[0].P.should.have.property('raw').equal(-1);
});
it("text is not 'init'", function () {
impedanceArray[0].P.should.have.property('text').equal(k.OBCIImpedanceTextInit);
});
});
describe('#inputN', function () {
it('got raw impedance value', function () {
impedanceArray[0].N.should.have.property('raw').equal(-1);
});
it("text is not 'init'", function () {
impedanceArray[0].N.should.have.property('text').equal(k.OBCIImpedanceTextInit);
});
});
});
describe('#channel2', function () {
it('has valid channel number', function () {
impedanceArray[1].channel.should.be.equal(2);
});
describe('#inputP', function () {
it('got raw impedance value', function () {
impedanceArray[1].P.should.have.property('raw').equal(-1);
});
it("text is not 'init'", function () {
impedanceArray[1].P.should.have.property('text').equal(k.OBCIImpedanceTextInit);
});
});
describe('#inputN', function () {
it('got raw impedance value', function () {
impedanceArray[1].N.should.have.property('raw').above(-1);
});
it("text is not 'init'", function () {
impedanceArray[1].N.should.have.property('text').not.be.equal(k.OBCIImpedanceTextInit);
});
});
});
describe('#channel3', function () {
it('has valid channel number', function () {
impedanceArray[2].channel.should.be.equal(3);
});
describe('#inputP', function () {
it('got raw impedance value', function () {
impedanceArray[2].P.should.have.property('raw').equal(-1);
});
it("text is not 'init'", function () {
impedanceArray[2].P.should.have.property('text').equal(k.OBCIImpedanceTextInit);
});
});
describe('#inputN', function () {
it('got raw impedance value', function () {
impedanceArray[2].N.should.have.property('raw').above(-1);
});
it("text is not 'init'", function () {
impedanceArray[2].N.should.have.property('text').not.be.equal(k.OBCIImpedanceTextInit);
});
});
});
describe('#channel4', function () {
it('has valid channel number', function () {
impedanceArray[3].channel.should.be.equal(4);
});
describe('#inputP', function () {
it('got raw impedance value', function () {
impedanceArray[3].P.should.have.property('raw').above(-1);
});
it("text is not 'init'", function () {
impedanceArray[3].P.should.have.property('text').not.be.equal(k.OBCIImpedanceTextInit);
});
});
describe('#inputN', function () {
it('got raw impedance value', function () {
impedanceArray[3].N.should.have.property('raw').equal(-1);
});
it("text is not 'init'", function () {
impedanceArray[3].N.should.have.property('text').equal(k.OBCIImpedanceTextInit);
});
});
});
describe('#channel5', function () {
it('has valid channel number', function () {
impedanceArray[4].channel.should.be.equal(5);
});
describe('#inputP', function () {
it('got raw impedance value', function () {
impedanceArray[4].P.should.have.property('raw').above(-1);
});
it("text is not 'init'", function () {
impedanceArray[4].P.should.have.property('text').not.be.equal(k.OBCIImpedanceTextInit);
});
});
describe('#inputN', function () {
it('got raw impedance value', function () {
impedanceArray[4].N.should.have.property('raw').equal(-1);
});
it("text is not 'init'", function () {
impedanceArray[4].N.should.have.property('text').equal(k.OBCIImpedanceTextInit);
});
});
});
describe('#channel6', function () {
it('has valid channel number', function () {
impedanceArray[5].channel.should.be.equal(6);
});
describe('#inputP', function () {
it('got raw impedance value', function () {
impedanceArray[5].P.should.have.property('raw').above(-1);
});
it("text is not 'init'", function () {
impedanceArray[5].P.should.have.property('text').not.be.equal(k.OBCIImpedanceTextInit);
});
});
describe('#inputN', function () {
it('got raw impedance value', function () {
impedanceArray[5].N.should.have.property('raw').equal(-1);
});
it("text is not 'init'", function () {
impedanceArray[5].N.should.have.property('text').equal(k.OBCIImpedanceTextInit);
});
});
});
describe('#channel7', function () {
it('has valid channel number', function () {
impedanceArray[6].channel.should.be.equal(7);
});
describe('#inputP', function () {
it('got raw impedance value', function () {
impedanceArray[6].P.should.have.property('raw').above(-1);
});
it("text is not 'init'", function () {
impedanceArray[6].P.should.have.property('text').not.be.equal(k.OBCIImpedanceTextInit);
});
});
describe('#inputN', function () {
it('got raw impedance value', function () {
impedanceArray[6].N.should.have.property('raw').above(-1);
});
it("text is not 'init'", function () {
impedanceArray[6].N.should.have.property('text').not.be.equal(k.OBCIImpedanceTextInit);
});
});
});
describe('#channel8', function () {
it('has valid channel number', function () {
impedanceArray[7].channel.should.be.equal(8);
});
describe('#inputP', function () {
it('got raw impedance value', function () {
impedanceArray[7].P.should.have.property('raw').above(-1);
});
it("text is not 'init'", function () {
impedanceArray[7].P.should.have.property('text').not.be.equal(k.OBCIImpedanceTextInit);
});
});
describe('#inputN', function () {
it('got raw impedance value', function () {
impedanceArray[7].N.should.have.property('raw').above(-1);
});
it("text is not 'init'", function () {
impedanceArray[7].N.should.have.property('text').not.be.equal(k.OBCIImpedanceTextInit);
});
});
});
});
describe('#impedanceTestChannel', function () {
var impedanceObject = {};
before(function (done) {
ourBoard.impedanceTestChannel(1)
.then(impdObj => {
impedanceObject = impdObj;
done();
})
.catch(err => done(err));
});
describe('#channel1', function () {
it('has valid channel number', function () {
impedanceObject.channel.should.be.equal(1);
});
describe('#inputP', function () {
it('got raw impedance value', function () {
impedanceObject.P.should.have.property('raw').above(-1);
});
it("text is not 'init'", function () {
impedanceObject.P.should.have.property('text').not.be.equal(k.OBCIImpedanceTextInit);
});
});
describe('#inputN', function () {
it('got raw impedance value', function () {
impedanceObject.N.should.have.property('raw').above(-1);
});
it("text is not 'init'", function () {
impedanceObject.N.should.have.property('text').not.be.equal(k.OBCIImpedanceTextInit);
});
});
});
});
describe('#impedanceTestChannelInputP', function () {
var impedanceObject = {};
before(function (done) {
ourBoard.impedanceTestChannelInputP(1)
.then(impdObj => {
impedanceObject = impdObj;
done();
})
.catch(err => done(err));
});
describe('#channel1', function () {
it('has valid channel number', function () {
impedanceObject.channel.should.be.equal(1);
});
describe('#inputP', function () {
it('got raw impedance value', function () {
impedanceObject.P.should.have.property('raw').above(-1);
});
it("text is not 'init'", function () {
impedanceObject.P.should.have.property('text').not.be.equal(k.OBCIImpedanceTextInit);
});
});
describe('#inputN', function () {
it('got raw impedance value', function () {
impedanceObject.N.should.have.property('raw').equal(-1);
});
it("text is not 'init'", function () {
impedanceObject.N.should.have.property('text').equal(k.OBCIImpedanceTextInit);
});
});
});
});
describe('#impedanceTestChannelInputN', function () {
var impedanceObject = {};
// wstream = fs.createWriteStream('hardwareVoltageOutputAll.txt')
before(function (done) {
console.log('7');
ourBoard.on('sample', sample => {
// console.log('8')
// OpenBCISample.debugPrettyPrint(sample)
// good to start impedance testing..
});
ourBoard.impedanceTestChannelInputN(1)
.then(impdObj => {
impedanceObject = impdObj;
setTimeout(() => {
done();
}, 1000);
})
.catch(err => done(err));
});
describe('#channel1', function () {
it('has valid channel number', function () {
impedanceObject.channel.should.be.equal(1);
});
describe('#inputP', function () {
it('got raw impedance value', function () {
impedanceObject.P.should.have.property('raw').equal(-1);
});
it("text is not 'init'", function () {
impedanceObject.P.should.have.property('text').equal(k.OBCIImpedanceTextInit);
});
});
describe('#inputN', function () {
it('got raw impedance value', function () {
impedanceObject.N.should.have.property('raw').above(-1);
});
it("text is not 'init'", function () {
impedanceObject.N.should.have.property('text').not.be.equal(k.OBCIImpedanceTextInit);
});
});
});
});
describe('#impedanceTestContinuousStXX', function () {
before(function (done) {
ourBoard.impedanceTestContinuousStart()
.then(done).catch(err => done(err));
});
after(function (done) {
ourBoard.impedanceTestContinuousStop()
.then(done);
});
it('prints 10 impedance arrays', function (done) {
var count = 1;
var listener = impedanceArray => {
// console.log('\nImpedance Array: ' + count)
// console.log(impedanceArray)
count++;
if (count > 10) {
ourBoard.removeListener('impedanceArray', listener);
done();
}
};
ourBoard.on('impedanceArray', listener);
});
});
describe('#_impedanceTestSetChannel', function () {
it('reject with invalid channel', function (done) {
ourBoard._impedanceTestSetChannel(0, false, false).should.be.rejected.and.notify(done);
});
});
describe('#_impedanceTestCalculateChannel', function () {
it('reject with low invalid channel', function (done) {
ourBoard._impedanceTestCalculateChannel(0, false, false).should.be.rejected.and.notify(done);
});
it('reject with high invalid channel', function (done) {
ourBoard._impedanceTestCalculateChannel(69, false, false).should.be.rejected.and.notify(done);
});
it('reject with invalid data type pInput', function (done) {
ourBoard._impedanceTestCalculateChannel(1, 'taco', false).should.be.rejected.and.notify(done);
});
it('reject with invalid data type nInput', function (done) {
ourBoard._impedanceTestCalculateChannel(1, false, 'taco').should.be.rejected.and.notify(done);
});
});
describe('#_impedanceTestFinalizeChannel', function () {
it('reject with low invalid channel', function (done) {
ourBoard._impedanceTestFinalizeChannel(0, false, false).should.be.rejected.and.notify(done);
});
it('reject with high invalid channel', function (done) {
ourBoard._impedanceTestFinalizeChannel(69, false, false).should.be.rejected.and.notify(done);
});
it('reject with invalid data type pInput', function (done) {
ourBoard._impedanceTestFinalizeChannel(1, 'taco', false).should.be.rejected.and.notify(done);
});
it('reject with invalid data type nInput', function (done) {
ourBoard._impedanceTestFinalizeChannel(1, false, 'taco').should.be.rejected.and.notify(done);
});
});
});
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+836
Ver Arquivo
@@ -0,0 +1,836 @@
'use strict';
var bluebirdChecks = require('./bluebirdChecks');
var bufferEqual = require('buffer-equal');
var chai = require('chai');
var chaiAsPromised = require(`chai-as-promised`);
var expect = chai.expect;
var should = chai.should(); // eslint-disable-line no-unused-vars
var openBCISimulator = require('../openBCISimulator');
var openBCISample = require('../openBCISample');
var k = openBCISample.k;
chai.use(chaiAsPromised);
describe('openBCISimulator', function () {
this.timeout(4000);
var portName = k.OBCISimulatorPortName;
afterEach(() => bluebirdChecks.noPendingPromises(200));
describe('#constructor', function () {
var simulator;
afterEach(() => {
simulator = null;
});
after(done => {
setTimeout(() => {
// Since there is a conditional timeout, it's important to wait to start the next test till this ends for sure
done();
}, 200); // The same amount of time in the simulator
});
it('constructs with the correct default options', function () {
simulator = new openBCISimulator.OpenBCISimulator();
expect(simulator.options.accel).to.be.true;
expect(simulator.options.alpha).to.be.true;
expect(simulator.options.boardFailure).to.be.false;
expect(simulator.options.daisy).to.be.false;
expect(simulator.options.drift).to.equal(0);
expect(simulator.options.firmwareVersion).to.equal(k.OBCIFirmwareV1);
expect(simulator.options.lineNoise).to.equal(k.OBCISimulatorLineNoiseHz60);
expect(simulator.options.sampleRate).to.equal(k.OBCISampleRate250);
expect(simulator.options.serialPortFailure).to.be.false;
expect(simulator.options.verbose).to.be.false;
expect(simulator.options.fragmentation).to.equal(k.OBCISimulatorFragmentationNone);
expect(simulator.options.latencyTime).to.equal(16);
expect(simulator.options.bufferSize).to.equal(4096);
});
it('should be able to get into daisy mode', function () {
simulator = new openBCISimulator.OpenBCISimulator(portName, {
daisy: true
});
expect(simulator.options.daisy).to.be.true;
});
it('should set the correct sample rate in daisy mode, if no sampleRate is provided', function () {
simulator = new openBCISimulator.OpenBCISimulator(portName, {
daisy: true
});
expect(simulator.options.sampleRate).to.equal(250); // produce samples at same rate
});
it('should use provided sample rate even if daisy is true', function () {
simulator = new openBCISimulator.OpenBCISimulator(portName, {
daisy: true,
sampleRate: 20
});
expect(simulator.options.daisy).to.be.true;
expect(simulator.options.sampleRate).to.equal(20);
});
it('should be able to put into firmware version 2', function () {
simulator = new openBCISimulator.OpenBCISimulator(portName, {
firmwareVersion: 'v2'
});
expect(simulator.options.firmwareVersion).to.equal(k.OBCIFirmwareV2);
});
it('should be able to simulate board failure', function () {
simulator = new openBCISimulator.OpenBCISimulator(portName, {
boardFailure: true
});
expect(simulator.options.boardFailure).to.be.true;
});
it('should be able to simulate serial port failure', function () {
simulator = new openBCISimulator.OpenBCISimulator(portName, {
serialPortFailure: true
});
expect(simulator.options.serialPortFailure).to.be.true;
});
it('can turn 50Hz line noise on', function () {
simulator = new openBCISimulator.OpenBCISimulator(portName, {
lineNoise: '50Hz'
});
(simulator.options.lineNoise).should.equal(k.OBCISimulatorLineNoiseHz50);
});
it('can turn no line noise on', function () {
simulator = new openBCISimulator.OpenBCISimulator(portName, {
lineNoise: 'none'
});
(simulator.options.lineNoise).should.equal(k.OBCISimulatorLineNoiseNone);
});
it('should not inject alpha if desired', function () {
simulator = new openBCISimulator.OpenBCISimulator(portName, {
alpha: false
});
expect(simulator.options.alpha).to.be.false;
});
it('should be able to not use the accel', function () {
simulator = new openBCISimulator.OpenBCISimulator(portName, {
accel: false
});
expect(simulator.options.accel).to.be.false;
});
it('should be able to set positive drift', function () {
simulator = new openBCISimulator.OpenBCISimulator(portName, {
drift: 1
});
expect(simulator.options.drift).to.be.greaterThan(0);
});
it('should be able to set negative drift', function () {
simulator = new openBCISimulator.OpenBCISimulator(portName, {
drift: -1
});
expect(simulator.options.drift).to.be.lessThan(0);
});
it('should throw if passed an invalid option', function (done) {
try {
simulator = new openBCISimulator.OpenBCISimulator(portName, {
foo: 'bar'
});
done('did not throw');
} catch (e) { done(); }
});
});
describe('#write', function () {
it('should refuse to write when not connected', function (done) {
var simulator = new openBCISimulator.OpenBCISimulator(k.OBCISimulatorPortName);
try {
simulator.write('q');
done('did not throw on disconnected write');
} catch (e) {
simulator.write('q', err => {
if (err) {
done();
} else {
done('did not provide error on disconnected write');
}
});
}
});
});
describe('#close', function () {
it('should provide an error closing when already closed', function (done) {
var simulator = new openBCISimulator.OpenBCISimulator(k.OBCISimulatorPortName);
simulator.close(err => {
if (err) {
done();
} else {
done('closed successfully but had no time to open');
}
});
});
});
describe(`_startStream`, function () {
it('should return a packet with sample data in it', function (done) {
var simulator = new openBCISimulator.OpenBCISimulator(k.OBCISimulatorPortName);
var sampleCounter = 0;
var sampleTestSize = 5;
var newDataFunc = data => {
if (sampleCounter > sampleTestSize) {
simulator.write(k.OBCIStreamStop);
simulator.removeListener('data', newDataFunc);
let sample = openBCISample.parseRawPacketStandard(data, k.channelSettingsArrayInit(k.OBCINumberOfChannelsDefault), true);
expect(sample.channelData).to.not.all.equal(0);
done();
simulator = null;
} else {
sampleCounter++;
}
};
simulator.on('data', newDataFunc);
simulator.once('open', () => simulator._startStream());
});
it('should return a sync set packet with accel', function (done) {
var simulator = new openBCISimulator.OpenBCISimulator(k.OBCISimulatorPortName);
var sampleCounter = 0;
var sampleTestSize = 5;
var newDataFunc = data => {
if (sampleCounter === 0) {
// Ensure everything is switched on for this test
simulator.options.accel = true;
simulator.synced = true;
simulator.sendSyncSetPacket = true;
expect(data[k.OBCIPacketPositionStopByte]).to.equal(openBCISample.makeTailByteFromPacketType(k.OBCIStreamPacketStandardAccel));
} else if (sampleCounter === 1) {
// Now this data should be the time sync up packet
expect(data[k.OBCIPacketPositionStopByte]).to.equal(openBCISample.makeTailByteFromPacketType(k.OBCIStreamPacketAccelTimeSyncSet));
// Expect flag to be down
expect(simulator.sendSyncSetPacket).to.be.false;
} else if (sampleCounter >= sampleTestSize) {
simulator.write(k.OBCIStreamStop);
simulator.removeListener('data', newDataFunc);
simulator = null;
done();
} else {
// Now this data should be the time sync up packet
expect(data[k.OBCIPacketPositionStopByte]).to.equal(openBCISample.makeTailByteFromPacketType(k.OBCIStreamPacketAccelTimeSynced));
}
sampleCounter++;
};
simulator.on('data', newDataFunc);
simulator.once('open', () => simulator.write(k.OBCIStreamStart));
});
it('should return a sync set packet with raw aux', function (done) {
var simulator = new openBCISimulator.OpenBCISimulator(k.OBCISimulatorPortName, {
accel: false
});
var sampleCounter = 0;
var sampleTestSize = 5;
var newDataFunc = data => {
if (sampleCounter === 0) {
// Ensure everything is switched on for this test
simulator.synced = true;
simulator.sendSyncSetPacket = true;
expect(data[k.OBCIPacketPositionStopByte]).to.equal(openBCISample.makeTailByteFromPacketType(k.OBCIStreamPacketStandardRawAux));
} else if (sampleCounter === 1) {
// Now this data should be the time sync up packet
expect(data[k.OBCIPacketPositionStopByte]).to.equal(openBCISample.makeTailByteFromPacketType(k.OBCIStreamPacketRawAuxTimeSyncSet));
// Expect flag to be down
expect(simulator.sendSyncSetPacket).to.be.false;
} else if (sampleCounter >= sampleTestSize) {
simulator.write(k.OBCIStreamStop);
simulator.removeListener('data', newDataFunc);
simulator = null;
done();
} else {
// Now this data should be the time sync up packet
expect(data[k.OBCIPacketPositionStopByte]).to.equal(openBCISample.makeTailByteFromPacketType(k.OBCIStreamPacketRawAuxTimeSynced));
}
sampleCounter++;
};
simulator.on('data', newDataFunc);
simulator.once('open', () => simulator.write(k.OBCIStreamStart));
});
});
describe(`firmwareVersion1`, function () {
var simulator;
beforeEach((done) => {
simulator = new openBCISimulator.OpenBCISimulator(k.OBCISimulatorPortName, {
firmwareVersion: 'v1'
});
simulator.once('open', done);
});
afterEach(() => {
simulator = null;
});
describe('reset', function () {
it('should not be v2', function (done) {
simulator.on('data', function (data) {
console.log(data.toString());
expect(data.toString().match('v2')).to.equal(null);
done();
});
simulator.write(k.OBCIMiscSoftReset);
});
});
});
describe(`firmwareVersion2`, function () {
var simulator;
beforeEach((done) => {
simulator = new openBCISimulator.OpenBCISimulator(k.OBCISimulatorPortName, {
firmwareVersion: 'v2'
});
simulator.once('open', done);
});
afterEach(() => {
simulator = null;
});
describe('reset', function () {
it('should be v2', function (done) {
simulator.on('data', function (data) {
console.log(data.toString());
expect(data.toString().match('v2')).to.not.equal(null);
done();
});
simulator.write(k.OBCIMiscSoftReset);
});
});
describe('_processPrivateRadioMessage', function () {
describe('OBCIRadioCmdChannelGet', function () {
it('should emit success if firmware version 2', done => {
simulator.channelNumber = 0;
var buf = new Buffer(0);
var dataEmit = data => {
buf = Buffer.concat([buf, data]);
if (openBCISample.doesBufferHaveEOT(buf)) {
expect(openBCISample.isSuccessInBuffer(buf)).to.be.true;
expect(openBCISample.isFailureInBuffer(buf)).to.be.false;
expect(buf[buf.length - 4]).to.equal(0);
simulator.removeListener('data', dataEmit);
done();
}
};
simulator.on('data', dataEmit);
simulator._processPrivateRadioMessage(new Buffer([k.OBCIRadioKey, k.OBCIRadioCmdChannelGet]));
});
it('should emit failure if board failure and host channel number', done => {
// Turn board failure mode
simulator.options.boardFailure = true;
simulator.channelNumber = 9;
var buf = new Buffer(0);
var dataEmit = data => {
buf = Buffer.concat([buf, data]);
if (openBCISample.doesBufferHaveEOT(buf)) {
expect(openBCISample.isSuccessInBuffer(buf)).to.be.false;
expect(openBCISample.isFailureInBuffer(buf)).to.be.true;
expect(buf[buf.length - 4]).to.equal(9);
simulator.removeListener('data', dataEmit);
done();
}
};
simulator.on('data', dataEmit);
simulator._processPrivateRadioMessage(new Buffer([k.OBCIRadioKey, k.OBCIRadioCmdChannelGet]));
});
});
describe('OBCIRadioCmdChannelSet', function () {
it('should set the channel number if in bounds', done => {
var newChanNum = 20;
var buf = new Buffer(0);
var dataEmit = data => {
buf = Buffer.concat([buf, data]);
if (openBCISample.doesBufferHaveEOT(buf)) {
expect(openBCISample.isSuccessInBuffer(buf)).to.be.true;
expect(openBCISample.isFailureInBuffer(buf)).to.be.false;
expect(buf[buf.length - 4]).to.equal(newChanNum);
expect(simulator.channelNumber).to.equal(newChanNum);
expect(simulator.hostChannelNumber).to.equal(newChanNum);
simulator.removeListener('data', dataEmit);
done();
}
};
simulator.on('data', dataEmit);
simulator._processPrivateRadioMessage(new Buffer([k.OBCIRadioKey, k.OBCIRadioCmdChannelSet, newChanNum]));
});
it('should not set the channel number if out of bounds', done => {
var newChanNum = 26;
var buf = new Buffer(0);
var dataEmit = data => {
buf = Buffer.concat([buf, data]);
if (openBCISample.doesBufferHaveEOT(buf)) {
expect(openBCISample.isSuccessInBuffer(buf)).to.be.false;
expect(openBCISample.isFailureInBuffer(buf)).to.be.true;
simulator.removeListener('data', dataEmit);
done();
}
};
simulator.on('data', dataEmit);
simulator._processPrivateRadioMessage(new Buffer([k.OBCIRadioKey, k.OBCIRadioCmdChannelSet, newChanNum]));
});
it('should emit failure if board failure', done => {
// Turn board failure mode
simulator.options.boardFailure = true;
var buf = new Buffer(0);
var dataEmit = data => {
buf = Buffer.concat([buf, data]);
if (openBCISample.doesBufferHaveEOT(buf)) {
expect(openBCISample.isSuccessInBuffer(buf)).to.be.false;
expect(openBCISample.isFailureInBuffer(buf)).to.be.true;
simulator.removeListener('data', dataEmit);
done();
}
};
simulator.on('data', dataEmit);
simulator._processPrivateRadioMessage(new Buffer([k.OBCIRadioKey, k.OBCIRadioCmdChannelSet, 7]));
});
});
describe('OBCIRadioCmdChannelSetOverride', function () {
it('should change just the hosts channel number and not the systems channel number and force a board comms failure', done => {
var systemChannelNumber = 0;
var newHostChannelNumber = 1;
simulator.channelNumber = systemChannelNumber;
var buf = new Buffer(0);
var dataEmit = data => {
buf = Buffer.concat([buf, data]);
if (openBCISample.doesBufferHaveEOT(buf)) {
expect(openBCISample.isSuccessInBuffer(buf)).to.be.true;
expect(openBCISample.isFailureInBuffer(buf)).to.be.false;
expect(buf[buf.length - 4]).to.equal(newHostChannelNumber);
expect(simulator.options.boardFailure).to.be.true;
expect(simulator.channelNumber).to.equal(systemChannelNumber);
expect(simulator.hostChannelNumber).to.equal(newHostChannelNumber);
simulator.removeListener('data', dataEmit);
done();
}
};
simulator.on('data', dataEmit);
simulator._processPrivateRadioMessage(new Buffer([k.OBCIRadioKey, k.OBCIRadioCmdChannelSetOverride, newHostChannelNumber]));
});
it('should change just the hosts channel number and not the systems channel number and fix a board failure', done => {
var systemChannelNumber = 0;
var oldHostChannelNumber = 1;
simulator.channelNumber = systemChannelNumber;
simulator.hostChannelNumber = oldHostChannelNumber;
var buf = new Buffer(0);
var dataEmit = data => {
buf = Buffer.concat([buf, data]);
if (openBCISample.doesBufferHaveEOT(buf)) {
expect(openBCISample.isSuccessInBuffer(buf)).to.be.true;
expect(openBCISample.isFailureInBuffer(buf)).to.be.false;
expect(buf[buf.length - 4]).to.equal(systemChannelNumber);
expect(simulator.options.boardFailure).to.be.false;
expect(simulator.channelNumber).to.equal(systemChannelNumber);
expect(simulator.hostChannelNumber).to.equal(systemChannelNumber);
simulator.removeListener('data', dataEmit);
done();
}
};
simulator.on('data', dataEmit);
simulator._processPrivateRadioMessage(new Buffer([k.OBCIRadioKey, k.OBCIRadioCmdChannelSetOverride, systemChannelNumber]));
});
it('should not set the channel number if out of bounds', done => {
var newChanNum = 26;
var buf = new Buffer(0);
var dataEmit = data => {
buf = Buffer.concat([buf, data]);
if (openBCISample.doesBufferHaveEOT(buf)) {
expect(openBCISample.isSuccessInBuffer(buf)).to.be.false;
expect(openBCISample.isFailureInBuffer(buf)).to.be.true;
simulator.removeListener('data', dataEmit);
done();
}
};
simulator.on('data', dataEmit);
simulator._processPrivateRadioMessage(new Buffer([k.OBCIRadioKey, k.OBCIRadioCmdChannelSetOverride, newChanNum]));
});
});
describe('OBCIRadioCmdPollTimeGet', function () {
it('should emit success if firmware version 2 with poll time', done => {
var expectedPollTime = 80;
simulator.pollTime = expectedPollTime;
var buf = new Buffer(0);
var dataEmit = data => {
buf = Buffer.concat([buf, data]);
if (openBCISample.doesBufferHaveEOT(buf)) {
expect(openBCISample.isSuccessInBuffer(buf)).to.be.true;
expect(openBCISample.isFailureInBuffer(buf)).to.be.false;
expect(buf[buf.length - 4]).to.equal(expectedPollTime);
simulator.removeListener('data', dataEmit);
done();
}
};
simulator.on('data', dataEmit);
simulator._processPrivateRadioMessage(new Buffer([k.OBCIRadioKey, k.OBCIRadioCmdPollTimeGet]));
});
it('should emit failure if board failure', done => {
// Turn board failure mode
simulator.options.boardFailure = true;
var buf = new Buffer(0);
var dataEmit = data => {
buf = Buffer.concat([buf, data]);
if (openBCISample.doesBufferHaveEOT(buf)) {
expect(openBCISample.isSuccessInBuffer(buf)).to.be.false;
expect(openBCISample.isFailureInBuffer(buf)).to.be.true;
simulator.removeListener('data', dataEmit);
done();
}
};
simulator.on('data', dataEmit);
simulator._processPrivateRadioMessage(new Buffer([k.OBCIRadioKey, k.OBCIRadioCmdPollTimeGet]));
});
});
describe('OBCIRadioCmdPollTimeSet', function () {
it('should set the poll time if in bounds', done => {
var newPollTime = 20;
var buf = new Buffer(0);
var dataEmit = data => {
buf = Buffer.concat([buf, data]);
if (openBCISample.doesBufferHaveEOT(buf)) {
expect(openBCISample.isSuccessInBuffer(buf)).to.be.true;
expect(openBCISample.isFailureInBuffer(buf)).to.be.false;
expect(buf[buf.length - 4]).to.equal(newPollTime);
simulator.removeListener('data', dataEmit);
done();
}
};
simulator.on('data', dataEmit);
simulator._processPrivateRadioMessage(new Buffer([k.OBCIRadioKey, k.OBCIRadioCmdPollTimeSet, newPollTime]));
});
it('should emit failure if board failure', done => {
// Turn board failure mode
simulator.options.boardFailure = true;
var buf = new Buffer(0);
var dataEmit = data => {
buf = Buffer.concat([buf, data]);
if (openBCISample.doesBufferHaveEOT(buf)) {
expect(openBCISample.isSuccessInBuffer(buf)).to.be.false;
expect(openBCISample.isFailureInBuffer(buf)).to.be.true;
simulator.removeListener('data', dataEmit);
done();
}
};
simulator.on('data', dataEmit);
simulator._processPrivateRadioMessage(new Buffer([k.OBCIRadioKey, k.OBCIRadioCmdPollTimeSet, 7]));
});
});
describe('OBCIRadioCmdBaudRateSetDefault', function () {
it('should emit success if firmware version 2 with proper baud rate', done => {
var buf = new Buffer(0);
var dataEmit = data => {
buf = Buffer.concat([buf, data]);
if (openBCISample.doesBufferHaveEOT(buf)) {
expect(openBCISample.isSuccessInBuffer(buf)).to.be.true;
expect(openBCISample.isFailureInBuffer(buf)).to.be.false;
var eotBuf = new Buffer('$$$');
var newBaudRateBuf;
for (var i = buf.length; i > 3; i--) {
if (bufferEqual(buf.slice(i - 3, i), eotBuf)) {
newBaudRateBuf = buf.slice(i - 9, i - 3);
break;
}
}
var newBaudRateNum = Number(newBaudRateBuf.toString());
expect(newBaudRateNum).to.equal(k.OBCIRadioBaudRateDefault);
simulator.removeListener('data', dataEmit);
done();
}
};
simulator.on('data', dataEmit);
simulator._processPrivateRadioMessage(new Buffer([k.OBCIRadioKey, k.OBCIRadioCmdBaudRateSetDefault]));
});
it('should emit success if board failure', done => {
// Turn board failure mode
simulator.options.boardFailure = true;
var buf = new Buffer(0);
var dataEmit = data => {
buf = Buffer.concat([buf, data]);
if (openBCISample.doesBufferHaveEOT(buf)) {
expect(openBCISample.isSuccessInBuffer(buf)).to.be.true;
expect(openBCISample.isFailureInBuffer(buf)).to.be.false;
simulator.removeListener('data', dataEmit);
done();
}
};
simulator.on('data', dataEmit);
simulator._processPrivateRadioMessage(new Buffer([k.OBCIRadioKey, k.OBCIRadioCmdBaudRateSetDefault]));
});
});
describe('OBCIRadioCmdBaudRateSetFast', function () {
it('should emit success if firmware version 2 with proper baud rate', done => {
var buf = new Buffer(0);
var dataEmit = data => {
buf = Buffer.concat([buf, data]);
if (openBCISample.doesBufferHaveEOT(buf)) {
expect(openBCISample.isSuccessInBuffer(buf)).to.be.true;
expect(openBCISample.isFailureInBuffer(buf)).to.be.false;
var eotBuf = new Buffer(`$$$`);
var newBaudRateBuf;
for (var i = buf.length; i > 3; i--) {
if (bufferEqual(buf.slice(i - 3, i), eotBuf)) {
newBaudRateBuf = buf.slice(i - 9, i - 3);
break;
}
}
var newBaudRateNum = Number(newBaudRateBuf.toString());
expect(newBaudRateNum).to.equal(k.OBCIRadioBaudRateFast);
simulator.removeListener('data', dataEmit);
done();
}
};
simulator.on('data', dataEmit);
simulator._processPrivateRadioMessage(new Buffer([k.OBCIRadioKey, k.OBCIRadioCmdBaudRateSetFast]));
});
it('should emit success if board failure', done => {
// Turn board failure mode
simulator.options.boardFailure = true;
var buf = new Buffer(0);
var dataEmit = data => {
buf = Buffer.concat([buf, data]);
if (openBCISample.doesBufferHaveEOT(buf)) {
expect(openBCISample.isSuccessInBuffer(buf)).to.be.true;
expect(openBCISample.isFailureInBuffer(buf)).to.be.false;
simulator.removeListener('data', dataEmit);
done();
}
};
simulator.on('data', dataEmit);
simulator._processPrivateRadioMessage(new Buffer([k.OBCIRadioKey, k.OBCIRadioCmdBaudRateSetFast]));
});
});
describe('OBCIRadioCmdSystemStatus', function () {
it('should emit success if firmware version 2', done => {
var buf = new Buffer(0);
var dataEmit = data => {
buf = Buffer.concat([buf, data]);
if (openBCISample.doesBufferHaveEOT(buf)) {
expect(openBCISample.isSuccessInBuffer(buf)).to.be.true;
expect(openBCISample.isFailureInBuffer(buf)).to.be.false;
simulator.removeListener('data', dataEmit);
done();
}
};
simulator.on('data', dataEmit);
simulator._processPrivateRadioMessage(new Buffer([k.OBCIRadioKey, k.OBCIRadioCmdSystemStatus]));
});
it('should emit failure if board failure', done => {
// Turn board failure mode
simulator.options.boardFailure = true;
var buf = new Buffer(0);
var dataEmit = data => {
buf = Buffer.concat([buf, data]);
if (openBCISample.doesBufferHaveEOT(buf)) {
expect(openBCISample.isSuccessInBuffer(buf)).to.be.false;
expect(openBCISample.isFailureInBuffer(buf)).to.be.true;
simulator.removeListener('data', dataEmit);
done();
}
};
simulator.on('data', dataEmit);
simulator._processPrivateRadioMessage(new Buffer([k.OBCIRadioKey, k.OBCIRadioCmdSystemStatus]));
});
});
});
});
describe('fragmentation', function () {
var simulator;
afterEach(done => {
simulator.removeAllListeners();
simulator.write(k.OBCIStreamStop);
simulator.close(done);
});
it('Should accumulate packets if set to FullBuffers', function (done) {
var bufferSize = 64;
simulator = new openBCISimulator.OpenBCISimulator(portName, {
fragmentation: k.OBCISimulatorFragmentationFullBuffers,
bufferSize: bufferSize,
latencyTime: 1000
});
simulator.on('data', function (buffer) {
expect(buffer.length).to.equal(bufferSize);
done();
});
simulator.once('open', () => simulator.write(k.OBCIStreamStart));
});
it('Should emit partial packets after latencyTime', function (done) {
var bufferSize = 4096;
simulator = new openBCISimulator.OpenBCISimulator(portName, {
fragmentation: k.OBCISimulatorFragmentationFullBuffers,
bufferSize: 4096,
latencyTime: 0
});
simulator.once('data', function (buffer) {
expect(buffer.length).to.be.lessThan(bufferSize);
done();
});
simulator.once('open', () => simulator.write(k.OBCIStreamStart));
});
it('Should emit single bytes if set to OneByOne', function (done) {
simulator = new openBCISimulator.OpenBCISimulator(portName, {
fragmentation: k.OBCISimulatorFragmentationOneByOne
});
var counter = 0;
simulator.on('data', function (buffer) {
expect(buffer.length).to.equal(1);
++counter;
if (counter === 5) done();
});
simulator.once('open', () => simulator.write(k.OBCIStreamStart));
});
it('should properly split packets, retaining valid packets', function (done) {
simulator = new openBCISimulator.OpenBCISimulator(portName, {
fragmentation: k.OBCISimulatorFragmentationRandom
});
var buffer = new Buffer(0);
var counter = 0;
simulator.on('data', function (data) {
buffer = Buffer.concat([buffer, data], buffer.length + data.length);
if (buffer.length >= 33) {
openBCISample.parseRawPacketStandard(buffer.slice(0, 33));
buffer = buffer.slice(33);
++counter;
if (counter === 5) done();
}
});
simulator.once('open', () => simulator.write(k.OBCIStreamStart));
});
});
describe(`boardFailure`, function () {});
describe(`#sync`, function () {
this.timeout(2000);
var simulator;
beforeEach(function (done) {
simulator = new openBCISimulator.OpenBCISimulator(portName, {
firmwareVersion: 'v2'
});
simulator.once('open', () => {
done();
});
});
afterEach(function () {
simulator = null;
});
it(`should emit the time sync sent command`, function (done) {
simulator.once('data', data => {
expect(openBCISample.isTimeSyncSetConfirmationInBuffer(data)).to.be.true;
done();
});
simulator.write(k.OBCISyncTimeSet, (err, msg) => {
if (err) {
done(err);
}
});
});
it(`should set synced to true`, function (done) {
simulator.synced = false;
var newData = data => {
expect(simulator.synced).to.be.true;
simulator.removeListener('data', newData);
done();
};
simulator.on('data', data => {
newData(data);
});
simulator.write(k.OBCISyncTimeSet, (err, msg) => {
if (err) {
done(err);
}
});
});
it(`should emit a time sync set packet followed by a time synced accel packet after sync up call`, function (done) {
simulator.synced = false;
var emitCounter = 0;
var maxPacketsBetweenSetPacket = 5;
var newData = data => {
if (emitCounter === 0) { // the time sync packet is emitted here
// Make a call to start streaming
simulator.write(k.OBCIStreamStart, err => {
if (err) done(err);
});
} else if (emitCounter < maxPacketsBetweenSetPacket) {
if (openBCISample.getRawPacketType(data[k.OBCIPacketPositionStopByte]) === k.OBCIStreamPacketAccelTimeSyncSet) {
simulator.removeListener('data', newData);
simulator.write(k.OBCIStreamStop, err => {
if (err) done(err);
done();
});
} else {
expect(openBCISample.getRawPacketType(data[k.OBCIPacketPositionStopByte])).to.equal(k.OBCIStreamPacketAccelTimeSynced);
}
} else {
done(`Failed to get set packet in time`);
}
emitCounter++;
};
simulator.on('data', newData);
simulator.write(k.OBCISyncTimeSet, (err, msg) => {
if (err) {
done(err);
}
});
});
it(`should emit a time sync set raw aux, then time synced raw aux packet after sync up call`, function (done) {
simulator.synced = false;
simulator.options.accel = false;
var emitCounter = 0;
var maxPacketsBetweenSetPacket = 5;
var newData = data => {
if (emitCounter === 0) { // the time sync packet is emitted here
// Make a call to start streaming
simulator.write(k.OBCIStreamStart, err => {
if (err) done(err);
});
} else if (emitCounter < maxPacketsBetweenSetPacket) {
if (openBCISample.getRawPacketType(data[k.OBCIPacketPositionStopByte]) === k.OBCIStreamPacketRawAuxTimeSyncSet) {
simulator.removeListener('data', newData);
simulator.write(k.OBCIStreamStop, err => {
if (err) done(err);
done();
});
} else {
expect(openBCISample.getRawPacketType(data[k.OBCIPacketPositionStopByte])).to.equal(k.OBCIStreamPacketRawAuxTimeSynced);
}
} else {
done(`Failed to get set packet in time`);
}
emitCounter++;
};
simulator.on('data', newData);
simulator.write(k.OBCISyncTimeSet, (err, msg) => {
if (err) {
done(err);
}
});
});
});
});
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+108
Ver Arquivo
@@ -0,0 +1,108 @@
// Converts timing events to use promises, to gain bluebird's checks
function instrumentTimingEvents (module, type) {
// replaces module[type] with a function that does the same thing but uses a promise
// assumes the first argument will be to a callback function
// if this a setSomething function with a clearSomething partner, the partner will also be instrumented
var setName = type;
var clearName = null;
if (type.substring(0, 3) === 'set') {
clearName = 'clear' + type.substring(3);
}
if (!module[setName]) return;
// store original functions
var originalSet = module[setName];
var originalClear = module[clearName];
exports[setName + 'Ignored'] = originalSet;
// dictionary to store promise details for each call
var events = {};
// setAsPromise() is the brunt of the function. It replaces the previous global function,
// and sets up a promise to resolve when the callback is called
var eventCount = 0;
var setAsPromise = function (callback) {
var args = [].slice.call(arguments);
var eventNum = ++eventCount;
var eventHandle;
if (setAsPromise._ignoreCount > 0) {
--setAsPromise._ignoreCount;
return originalSet.apply(this, args);
}
// actual callback is replaced by promise resolve
args[0] = function () {
if (!events[eventNum]) throw new Error(setName + ' ' + eventNum + ' disappeared');
events[eventNum].resolve([].slice.call(arguments));
};
eventHandle = originalSet.apply(this, args) || eventNum;
// this portion is a function so that setInterval may be handled via recursion
function dispatch () {
var handlerDetails = { handle: eventHandle };
var promise = new Promise((resolve, reject) => {
handlerDetails.resolve = resolve;
handlerDetails.reject = reject;
});
handlerDetails.promise = promise;
events[eventNum] = handlerDetails;
promise.then(function (argumentArray) {
if (type !== 'setInterval') {
delete events[eventNum];
} else {
dispatch();
}
// call original handler
callback.apply(this, argumentArray);
}, () => {
originalClear(eventHandle);
delete events[eventNum];
});
return promise;
}
dispatch();
return eventNum;
};
// actually replace functions with instrumented ones
setAsPromise._ignoreCount = 0;
module[setName] = setAsPromise;
Object.defineProperty(setAsPromise, 'name', { value: setName + 'AsPromise' });
if (clearName) {
module[clearName] = (eventNum) => {
if (!events[eventNum]) {
originalClear(eventNum);
} else {
events[eventNum].reject(new Error('cleared'));
}
};
Object.defineProperty(module[clearName], 'name', { value: clearName + 'AsPromise' });
}
}
instrumentTimingEvents(global, 'setTimeout');
instrumentTimingEvents(global, 'setInterval');
instrumentTimingEvents(global, 'setImmediate');
// // Possible TODO: nextTick needs some exceptions included to prevent infinite recursion
// instrumentTimingEvents(process, 'nextTick');
// the next call to the passed function should not be promisified
// may be queued multiple times
exports.ignoreOnce = (ignored) => {
ignored._ignoreCount ++;
};
-135
Ver Arquivo
@@ -1,135 +0,0 @@
// This takes a openbci-sdk factory and mocks the shit out of it in complete isolation per require of this file
"use strict";
var Hardware = function () {
this.bciBoard = {};
//this.mockBinding = {
// connect: this.connect.bind(this),
// disconnect: this.disconnect.bind(this),
// streamStart: this.streamStart.bind(this),
// streamStop: this.streamStop.bind(this),
// write: this.write.bind(this),
// softReset: this.softReset.bind(this),
// autoFindOpenBCIBoard: this.autoFindOpenBCIBoard.bind(this),
// simulatorEnable: this.simulatorEnable.bind(this),
// simulatorDisable: this.simulatorDisable.bind(this)
//};
};
Hardware.prototype.reset = function () {
this.bciBoard = {};
};
Hardware.prototype.createBoard = function () {
this.bciBoard = {
serial: null,
connected: false,
streaming: false,
isSimulating: false,
badPackets: 0,
bytesIn: 0,
commandsToWrite: 0,
sampleCount: 0
}
};
Hardware.prototype.connect = function (portName) {
return new Promise((resolve, reject) => {
if(!this.bciBoard) reject('Board does not exist - call hardware.createBoard() first');
this.bciBoard.connected = true;
this.bciBoard.serial = {
portName:portName,
baudRate:115200
};
resolve(this.bciBoard.serial);
});
};
Hardware.prototype.disconnect = function () {
return new Promise((resolve,reject) => {
if(!this.bciBoard) reject('Board does not exist - call hardware.createBoard() first');
this.bciBoard.connected = false;
this.bciBoard.serial = null;
});
};
Hardware.prototype.streamStart = function () {
return new Promise((resolve,reject) => {
if(!this.bciBoard) reject('Board does not exist - call hardware.createBoard() first');
this.bciBoard.streaming = true;
resolve();
});
};
Hardware.prototype.streamStop = function () {
return new Promise((resolve,reject) => {
if(!this.bciBoard) reject('Board does not exist - call hardware.createBoard() first');
this.bciBoard.streaming = false;
resolve();
});
};
Hardware.prototype.simulatorEnable = function () {
return new Promise((resolve,reject) => {
if(!this.bciBoard) reject('Board does not exist - call hardware.createBoard() first');
this.bciBoard.isSimulating = true;
resolve();
});
};
Hardware.prototype.simulatorDisable = function () {
return new Promise((resolve,reject) => {
if(!this.bciBoard) reject('Board does not exist - call hardware.createBoard() first');
this.bciBoard.isSimulating = false;
resolve();
});
};
Hardware.prototype.autoFindOpenBCIBoard = function () {
return new Promise((resolve,reject) => {
resolve('/dev/tty.usbserial-D069XXX');
});
};
Hardware.prototype.emitSample = function (data) {
return new Promise((resolve,reject) => {
if(!this.bciBoard) reject('Board does not exist - call hardware.createBoard() first');
this.bciBoard.isSimulating = false;
resolve();
});
};
Hardware.prototype.fakeData = function (data) {
//do something, not quite sure what yet...
};
var hardware = new Hardware();
var SandboxedModule = require('sandboxed-module');
var openBCIBoard = SandboxedModule.require('../openBCIBoard', {
requires: {
fs: {
read: hardware.fakeData.bind(hardware)
}
},
globals: {
process: {
platform: 'darwin',
nextTick: process.nextTick
}
}
});
openBCIBoard.hardware = hardware;
module.exports = openBCIBoard;