├── .bithoundrc ├── .eslintrc ├── .gitignore ├── .jsinitrc ├── .npmignore ├── .travis.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENCE.txt ├── PIGPIO ├── MakeRemote ├── Makefile ├── README ├── UNLICENCE ├── build │ ├── lib.linux-x86_64-2.7 │ │ └── pigpio.py │ └── lib │ │ └── pigpio.py ├── command.c ├── command.h ├── command.o ├── custom.cext ├── libpigpio.so ├── libpigpiod_if.so ├── libpigpiod_if2.so ├── pig2vcd ├── pig2vcd.1 ├── pig2vcd.c ├── pig2vcd.o ├── pigpio.3 ├── pigpio.c ├── pigpio.h ├── pigpio.o ├── pigpio.py ├── pigpiod ├── pigpiod.1 ├── pigpiod.c ├── pigpiod.o ├── pigpiod_if.3 ├── pigpiod_if.c ├── pigpiod_if.h ├── pigpiod_if.o ├── pigpiod_if2.3 ├── pigpiod_if2.c ├── pigpiod_if2.h ├── pigpiod_if2.o ├── pigs ├── pigs.1 ├── pigs.c ├── pigs.o ├── setup.py ├── x_pigpio ├── x_pigpio.c ├── x_pigpio.o ├── x_pigpio.py ├── x_pigpiod_if ├── x_pigpiod_if.c ├── x_pigpiod_if.o ├── x_pigpiod_if2 ├── x_pigpiod_if2.c ├── x_pigpiod_if2.o ├── x_pigs └── x_pipe ├── README.md ├── docs ├── Buzzer.html ├── CompositeDevice.html ├── CompositeOutputDevice.html ├── Device.html ├── DigitalInputDevice.html ├── DigitalOutputDevice.html ├── GPIODevice.html ├── InputDevice.html ├── LED.html ├── LEDBoard.html ├── LEDCollection.html ├── MockPin.html ├── MockPulledUpPin.html ├── Motor.html ├── OutputDevice.html ├── PWMLED.html ├── PWMOutputDevice.html ├── PiTraffic.html ├── Pin.html ├── RGBLED.html ├── TrafficLights.html ├── assets │ ├── anchor.js │ ├── bass-addons.css │ ├── bass.css │ ├── fonts │ │ ├── EOT │ │ │ ├── SourceCodePro-Bold.eot │ │ │ └── SourceCodePro-Regular.eot │ │ ├── LICENSE.txt │ │ ├── OTF │ │ │ ├── SourceCodePro-Bold.otf │ │ │ └── SourceCodePro-Regular.otf │ │ ├── TTF │ │ │ ├── SourceCodePro-Bold.ttf │ │ │ └── SourceCodePro-Regular.ttf │ │ ├── WOFF │ │ │ ├── OTF │ │ │ │ ├── SourceCodePro-Bold.otf.woff │ │ │ │ └── SourceCodePro-Regular.otf.woff │ │ │ └── TTF │ │ │ │ ├── SourceCodePro-Bold.ttf.woff │ │ │ │ └── SourceCodePro-Regular.ttf.woff │ │ ├── WOFF2 │ │ │ ├── OTF │ │ │ │ ├── SourceCodePro-Bold.otf.woff2 │ │ │ │ └── SourceCodePro-Regular.otf.woff2 │ │ │ └── TTF │ │ │ │ ├── SourceCodePro-Bold.ttf.woff2 │ │ │ │ └── SourceCodePro-Regular.ttf.woff2 │ │ └── source-code-pro.css │ ├── github.css │ ├── site.js │ └── style.css ├── boards.js.html ├── boards_LEDBoard.js.html ├── boards_LEDCollection.js.html ├── boards_PiTraffic.js.html ├── boards_TrafficLights.js.html ├── devices.js.html ├── devices_CompositeDevice.js.html ├── devices_Device.js.html ├── devices_GPIODevice.js.html ├── fonts │ ├── OpenSans-Bold-webfont.eot │ ├── OpenSans-Bold-webfont.svg │ ├── OpenSans-Bold-webfont.woff │ ├── OpenSans-BoldItalic-webfont.eot │ ├── OpenSans-BoldItalic-webfont.svg │ ├── OpenSans-BoldItalic-webfont.woff │ ├── OpenSans-Italic-webfont.eot │ ├── OpenSans-Italic-webfont.svg │ ├── OpenSans-Italic-webfont.woff │ ├── OpenSans-Light-webfont.eot │ ├── OpenSans-Light-webfont.svg │ ├── OpenSans-Light-webfont.woff │ ├── OpenSans-LightItalic-webfont.eot │ ├── OpenSans-LightItalic-webfont.svg │ ├── OpenSans-LightItalic-webfont.woff │ ├── OpenSans-Regular-webfont.eot │ ├── OpenSans-Regular-webfont.svg │ └── OpenSans-Regular-webfont.woff ├── index.html ├── index.js.html ├── input_devices_DigitalInputDevice.js.html ├── input_devices_InputDevice.js.html ├── output_devices.js.html ├── output_devices_Buzzer.js.html ├── output_devices_CompositeOutputDevice.js.html ├── output_devices_DigitalOutputDevice.js.html ├── output_devices_LED.js.html ├── output_devices_Motor.js.html ├── output_devices_OutputDevice.js.html ├── output_devices_PWMLED.js.html ├── output_devices_PWMOutputDevice.js.html ├── output_devices_RGBLED.js.html ├── pins_index.js.html ├── pins_mock.js.html ├── scripts │ ├── linenumber.js │ └── prettify │ │ ├── Apache-License-2.0.txt │ │ ├── lang-css.js │ │ └── prettify.js └── styles │ ├── jsdoc-default.css │ ├── jsdoc.css │ ├── prettify-jsdoc.css │ ├── prettify-tomorrow.css │ └── prettify.css ├── gpiozero ├── Mixins │ └── EventsMixin.js ├── boards │ ├── LEDBoard.js │ ├── LEDCollection.js │ ├── PiTraffic.js │ └── TrafficLights.js ├── compat.js ├── devices │ ├── CompositeDevice.js │ ├── Device.js │ └── GPIODevice.js ├── exc.js ├── index.js ├── input_devices │ ├── DigitalInputDevice.js │ └── InputDevice.js ├── output_devices │ ├── Buzzer.js │ ├── CompositeOutputDevice.js │ ├── DigitalOutputDevice.js │ ├── LED.js │ ├── Motor.js │ ├── OutputDevice.js │ ├── PWMLED.js │ ├── PWMOutputDevice.js │ └── RGBLED.js ├── pins │ ├── index.js │ ├── mock.js │ └── wiringpi.js └── tools.js ├── jsdoc.json ├── package.json ├── pre-commit.sh ├── renovate.json └── test ├── boards.spec.js ├── devices.spec.js ├── eslint.spec.js ├── input_devices.spec.js ├── mocha.opts └── output_devices.spec.js /.bithoundrc: -------------------------------------------------------------------------------- 1 | { 2 | "ignore": [ 3 | "**/deps/**", 4 | "**/node_modules/**", 5 | "**/thirdparty/**", 6 | "**/third_party/**", 7 | "**/vendor/**", 8 | "**/**-min-**", 9 | "**/**-min.**", 10 | "**/**.min.**", 11 | "**/**jquery.?(ui|effects)-*.*.?(*).?(cs|j)s", 12 | "**/**jquery-*.*.?(*).?(cs|j)s", 13 | "**/prototype?(*).js", 14 | "**/mootools*.*.*.js", 15 | "**/dojo.js", 16 | "**/MochiKit.js", 17 | "**/yahoo-*.js", 18 | "**/yui*.js", 19 | "**/ckeditor*.js", 20 | "**/tiny_mce*.js", 21 | "**/tiny_mce/?(langs|plugins|themes|utils)/**", 22 | "**/MathJax/**", 23 | "**/shBrush*.js", 24 | "**/shCore.js", 25 | "**/shLegacy.js", 26 | "**/modernizr.custom.?(*).js", 27 | "**/knockout-*.*.*.debug.js", 28 | "**/extjs/*.js", 29 | "**/extjs/*.xml", 30 | "**/extjs/*.txt", 31 | "**/extjs/*.html", 32 | "**/extjs/*.properties", 33 | "**/extjs/.sencha", 34 | "**/extjs/docs/**", 35 | "**/extjs/builds/**", 36 | "**/extjs/cmd/**", 37 | "**/extjs/examples/**", 38 | "**/extjs/locale/**", 39 | "**/extjs/packages/**", 40 | "**/extjs/plugins/**", 41 | "**/extjs/resources/**", 42 | "**/extjs/src/**", 43 | "**/extjs/welcome/**", 44 | "bower_components/**", 45 | "**/docs/**" 46 | ], 47 | "test": [ 48 | "**/test/**", 49 | "**/tests/**", 50 | "**/spec/**", 51 | "**/specs/**" 52 | ] 53 | } -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "rules": { 4 | "no-var" : "off", 5 | "import/no-commonjs" : "off", 6 | "jsdoc/check-param-names": 1, 7 | "jsdoc/check-tag-names": 1, 8 | "jsdoc/check-types": 1, 9 | "jsdoc/newline-after-description": 1, 10 | "jsdoc/require-description-complete-sentence": 1, 11 | "jsdoc/require-hyphen-before-param-description": 1, 12 | "jsdoc/require-param": 1, 13 | "jsdoc/require-param-description": 1, 14 | "jsdoc/require-param-type": 1, 15 | "jsdoc/require-returns-description": 1, 16 | "jsdoc/require-returns-type": 1 17 | }, 18 | "extends": ["node"], 19 | "plugins": [ 20 | "jsdoc" 21 | ] 22 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | coverage 4 | .idea 5 | dist 6 | -------------------------------------------------------------------------------- /.jsinitrc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketrebilcock/js-gpiozero/8d02c3b65604cdd34a0f5ce7c8f905647237dc21/.jsinitrc -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | coverage 2 | test 3 | docs -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | cache: 3 | directories: 4 | - node_modules 5 | node_js: 6 | - '7' 7 | - '6' 8 | install: 9 | - npm install 10 | script: 11 | - npm test 12 | env: 13 | matrix: 14 | - CXX=g++-4.8 15 | global: 16 | secure: PmiPta2PsLKwMKi35LEle0f9n95hODkuBCFHzKbJ9r2Tn/1q31g/o3dJQ/5a2D+N0GhSrj+QA2lmeXp7UyMzNACWNsEhiqz+0rGMuBF0qzdfJN4ilYDg+HqZbUlplY/BISrdpI3VW995Lii3THlYFSxNMIzFV83LUdE4oPi9ETLHVLTRJcbkabq2Bn0NQ+Y0WAi8FVUluHUgRoDljpsivW/vRN9vnf0559ZuZRBBx4dwEcyW5/7/yug5fqdu476xyE53W27X1YBwrdHEy6IIC6aeagda0g5C2J7WrUzO6a2E3gIFYLr9CQkKzov8mKrg2xXAHxgXs51owreV1HstGtxUPcwFNZDGgSyPgawZojSKWYBwr4Mewu8UOQyrzZDZJa7sILBznMuHS8756N5rq7PXwU76H4UQv9aGPfV7dXIeL2UhCQdMllovVU2cd+YT/Fz/2FRTZsYF8h91Iowuyp8pMpqeeaFQ76YDLH4hYlYRPjKdK6XUPvidEpeOO5LDHzm2pNBNf/WEWZioH1gqP9viOBlhrEXuuh4Ugxj2we5BlwjLEcy/J/kqmW2uLrbcbNs8tLhG/0qhlAuHeWz+aHpJshwdMSural3fqkeZDMbEkeFTYwhRmLm6Pz09cSShdY+AUs1cG8qoxQ84SjbGk9ibTJnEYvrWc/6ZsJxABEY= 17 | addons: 18 | apt: 19 | sources: 20 | - ubuntu-toolchain-r-test 21 | packages: 22 | - g++-4.8 23 | before_script: 24 | - npm prune 25 | after_success: 26 | - npm run semantic-release 27 | branches: 28 | except: 29 | - /^v\d+\.\d+\.\d+$/ 30 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | # [1.0.0](https://github.com/i-am-digital/js-gpiozero/compare/1.0.0...v1.0.0) (2016-12-29) 3 | 4 | 5 | 6 | 7 | 8 | ## [0.1.5](https://github.com/i-am-digital/js-gpiozero/compare/0.1.5...v0.1.5) (2016-12-27) 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # js-gpiozero is an OPEN Open Source Project 2 | 3 | ----------------------------------------- 4 | 5 | ## What? 6 | 7 | Individuals making significant and valuable contributions are given commit-access to the project to contribute as they see fit. This project is more like an open wiki than a standard guarded open source project. 8 | 9 | ## Rules 10 | 11 | There are a few basic ground-rules for contributors: 12 | 13 | 1. **No `--force` pushes** or modifying the Git history in any way. 14 | 1. **Non-master branches** ought to be used for ongoing work. 15 | 1. **External API changes and significant modifications** ought to be subject to an **internal pull-request** to solicit feedback from other contributors. 16 | 1. Internal pull-requests to solicit feedback are *encouraged* for any other non-trivial contribution but left to the discretion of the contributor. 17 | 1. Contributors should attempt to adhere to the prevailing code-style. 18 | 19 | ## Releases 20 | 21 | Declaring formal releases remains the prerogative of the project maintainer. 22 | 23 | ## Changes to this arrangement 24 | 25 | This is an experiment and feedback is welcome! This document may also be subject to pull-requests or changes by contributors where you believe you have something valuable to add or change. 26 | 27 | [this approach is totally cribbed from the excellent documentation project](https://github.com/documentationjs/documentation/blob/master/CONTRIBUTING.md) 28 | 29 | ---- 30 | 31 | ## Releasing 32 | 33 | js-gpiozero uses [semantic-release](https://github.com/semantic-release/semantic-release) to deploy code as often as possible. We use [standard-changelog](https://github.com/conventional-changelog/standard-changelog) 34 | to generate CHANGELOG.md entries and [commitizen](https://github.com/commitizen/cz-cli) to standardize 35 | commit messages. Pull Request messages should be standardized to commitizen syntax (aka angular standard) 36 | before merge. 37 | 38 | Release process (completed by semantic-release): 39 | 40 | * Confirm that `master` passes CI tests 41 | * Bump version in `package.json` 42 | * Add Version Tag to Git 43 | * Run `npm run changelog` 44 | * Add updated CHANGELOG.md to master 45 | * Push commits and new tag 46 | * npm publish 47 | 48 | -------------------------------------------------------------------------------- /LICENCE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2016 js-gpiozero 2 | 3 | Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. 4 | 5 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -------------------------------------------------------------------------------- /PIGPIO/MakeRemote: -------------------------------------------------------------------------------- 1 | # 2 | CC = gcc 3 | SIZE = size 4 | SHLIB = gcc -shared 5 | STRIPLIB = strip --strip-unneeded 6 | 7 | CFLAGS += -O3 -Wall -pthread 8 | 9 | ALL = libpigpiod_if.so libpigpiod_if2.so pigs x_pigpiod_if x_pigpiod_if2 10 | 11 | prefix = /usr/local 12 | exec_prefix = $(prefix) 13 | bindir = $(exec_prefix)/bin 14 | includedir = $(prefix)/include 15 | libdir = $(prefix)/lib 16 | mandir = $(prefix)/man 17 | 18 | all: $(ALL) pigpio.py setup.py 19 | 20 | pigpiod_if.o: pigpiod_if.c pigpio.h command.h pigpiod_if.h 21 | $(CC) $(CFLAGS) -fpic -c -o pigpiod_if.o pigpiod_if.c 22 | 23 | pigpiod_if2.o: pigpiod_if2.c pigpio.h command.h pigpiod_if2.h 24 | $(CC) $(CFLAGS) -fpic -c -o pigpiod_if2.o pigpiod_if2.c 25 | 26 | command.o: command.c pigpio.h command.h 27 | $(CC) $(CFLAGS) -fpic -c -o command.o command.c 28 | 29 | pigs: command.o pigs.o 30 | $(CC) $(CFLAGS) -fpic -o pigs pigs.c command.c 31 | 32 | x_pigpiod_if: x_pigpiod_if.o $(LIB1) 33 | $(CC) -o x_pigpiod_if x_pigpiod_if.o $(LL1) 34 | 35 | x_pigpiod_if2: x_pigpiod_if2.o $(LIB2) 36 | $(CC) -o x_pigpiod_if2 x_pigpiod_if2.o $(LL2) 37 | 38 | clean: 39 | rm -f *.o *.i *.s *~ $(ALL) 40 | 41 | install: $(LIB1) $(LIB2) 42 | install -m 0755 -d $(DESTDIR)$(includedir) 43 | install -m 0644 pigpio.h $(DESTDIR)$(includedir) 44 | install -m 0644 pigpiod_if.h $(DESTDIR)$(includedir) 45 | install -m 0644 pigpiod_if2.h $(DESTDIR)$(includedir) 46 | install -m 0755 -d $(DESTDIR)$(libdir) 47 | install -m 0644 libpigpiod_if.so $(DESTDIR)$(libdir) 48 | install -m 0644 libpigpiod_if2.so $(DESTDIR)$(libdir) 49 | install -m 0755 -d $(DESTDIR)$(bindir) 50 | install -m 0755 pigs $(DESTDIR)$(bindir) 51 | python2 setup.py install 52 | python3 setup.py install 53 | install -m 0755 -d $(DESTDIR)$(mandir)/man1 54 | install -m 0644 *.1 $(DESTDIR)$(mandir)/man1 55 | install -m 0755 -d $(DESTDIR)$(mandir)/man3 56 | install -m 0644 *.3 $(DESTDIR)$(mandir)/man3 57 | 58 | uninstall: 59 | rm -f $(DESTDIR)$(includedir)/pigpio.h 60 | rm -f $(DESTDIR)$(includedir)/pigpiod_if.h 61 | rm -f $(DESTDIR)$(includedir)/pigpiod_if2.h 62 | rm -f $(DESTDIR)$(libdir)/libpigpiod_if.so 63 | rm -f $(DESTDIR)$(libdir)/libpigpiod_if2.so 64 | echo removing python2 files 65 | python2 setup.py install --record /tmp/pigpio >/dev/null 66 | xargs rm -f < /tmp/pigpio >/dev/null 67 | echo removing python3 files 68 | python3 setup.py install --record /tmp/pigpio >/dev/null 69 | xargs rm -f < /tmp/pigpio >/dev/null 70 | rm -f $(DESTDIR)$(bindir)/pigs 71 | rm -f $(DESTDIR)$(mandir)/man1/pig*.1 72 | rm -f $(DESTDIR)$(mandir)/man3/pig*.3 73 | 74 | LL1 = -L. -lpigpiod_if -pthread -lrt 75 | LL2 = -L. -lpigpiod_if2 -pthread -lrt 76 | 77 | LIB1 = libpigpiod_if.so 78 | OBJ1 = pigpiod_if.o command.o 79 | 80 | LIB2 = libpigpiod_if2.so 81 | OBJ2 = pigpiod_if2.o command.o 82 | 83 | $(LIB1): $(OBJ1) 84 | $(SHLIB) -o $(LIB1) $(OBJ1) 85 | $(STRIPLIB) $(LIB1) 86 | $(SIZE) $(LIB1) 87 | 88 | $(LIB2): $(OBJ2) 89 | $(SHLIB) -o $(LIB2) $(OBJ2) 90 | $(STRIPLIB) $(LIB2) 91 | $(SIZE) $(LIB2) 92 | 93 | # generated using gcc -MM *.c 94 | 95 | command.o: command.c pigpio.h command.h 96 | pigpiod.o: pigpiod.c pigpio.h 97 | pigpiod_if.o: pigpiod_if.c pigpio.h pigpiod_if.h command.h 98 | pigpiod_if2.o: pigpiod_if2.c pigpio.h pigpiod_if2.h command.h 99 | pigs.o: pigs.c pigpio.h command.h 100 | 101 | 102 | -------------------------------------------------------------------------------- /PIGPIO/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Set CROSS_PREFIX to prepend to all compiler tools at once for easier 3 | # cross-compilation. 4 | CROSS_PREFIX = 5 | CC = $(CROSS_PREFIX)gcc 6 | AR = $(CROSS_PREFIX)ar 7 | RANLIB = $(CROSS_PREFIX)ranlib 8 | SIZE = $(CROSS_PREFIX)size 9 | STRIP = $(CROSS_PREFIX)strip 10 | SHLIB = $(CC) -shared 11 | STRIPLIB = $(STRIP) --strip-unneeded 12 | 13 | CFLAGS += -O3 -Wall -pthread 14 | 15 | LIB1 = libpigpio.so 16 | OBJ1 = pigpio.o command.o 17 | 18 | LIB2 = libpigpiod_if.so 19 | OBJ2 = pigpiod_if.o command.o 20 | 21 | LIB3 = libpigpiod_if2.so 22 | OBJ3 = pigpiod_if2.o command.o 23 | 24 | LIB = $(LIB1) $(LIB2) $(LIB3) 25 | 26 | ALL = $(LIB) x_pigpio x_pigpiod_if x_pigpiod_if2 pig2vcd pigpiod pigs 27 | 28 | LL1 = -L. -lpigpio -pthread -lrt 29 | 30 | LL2 = -L. -lpigpiod_if -pthread -lrt 31 | 32 | LL3 = -L. -lpigpiod_if2 -pthread -lrt 33 | 34 | prefix = /usr/local 35 | exec_prefix = $(prefix) 36 | bindir = $(exec_prefix)/bin 37 | includedir = $(prefix)/include 38 | libdir = $(prefix)/lib 39 | mandir = $(prefix)/man 40 | 41 | all: $(ALL) 42 | 43 | pigpio.o: pigpio.c pigpio.h command.h custom.cext 44 | $(CC) $(CFLAGS) -fpic -c -o pigpio.o pigpio.c 45 | 46 | pigpiod_if.o: pigpiod_if.c pigpio.h command.h pigpiod_if.h 47 | $(CC) $(CFLAGS) -fpic -c -o pigpiod_if.o pigpiod_if.c 48 | 49 | pigpiod_if2.o: pigpiod_if2.c pigpio.h command.h pigpiod_if2.h 50 | $(CC) $(CFLAGS) -fpic -c -o pigpiod_if2.o pigpiod_if2.c 51 | 52 | command.o: command.c pigpio.h command.h 53 | $(CC) $(CFLAGS) -fpic -c -o command.o command.c 54 | 55 | x_pigpio: x_pigpio.o $(LIB1) 56 | $(CC) -o x_pigpio x_pigpio.o $(LL1) 57 | 58 | x_pigpiod_if: x_pigpiod_if.o $(LIB2) 59 | $(CC) -o x_pigpiod_if x_pigpiod_if.o $(LL2) 60 | 61 | x_pigpiod_if2: x_pigpiod_if2.o $(LIB3) 62 | $(CC) -o x_pigpiod_if2 x_pigpiod_if2.o $(LL3) 63 | 64 | pigpiod: pigpiod.o $(LIB1) 65 | $(CC) -o pigpiod pigpiod.o $(LL1) 66 | $(STRIP) pigpiod 67 | 68 | pigs: pigs.o command.o 69 | $(CC) -o pigs pigs.o command.o 70 | $(STRIP) pigs 71 | 72 | pig2vcd: pig2vcd.o 73 | $(CC) -o pig2vcd pig2vcd.o 74 | $(STRIP) pig2vcd 75 | 76 | clean: 77 | rm -f *.o *.i *.s *~ $(ALL) 78 | 79 | install: $(ALL) 80 | install -m 0755 -d $(DESTDIR)/opt/pigpio/cgi 81 | install -m 0755 -d $(DESTDIR)$(includedir) 82 | install -m 0644 pigpio.h $(DESTDIR)$(includedir) 83 | install -m 0644 pigpiod_if.h $(DESTDIR)$(includedir) 84 | install -m 0644 pigpiod_if2.h $(DESTDIR)$(includedir) 85 | install -m 0755 -d $(DESTDIR)$(libdir) 86 | install -m 0755 libpigpio.so $(DESTDIR)$(libdir) 87 | install -m 0755 libpigpiod_if.so $(DESTDIR)$(libdir) 88 | install -m 0755 libpigpiod_if2.so $(DESTDIR)$(libdir) 89 | install -m 0755 -d $(DESTDIR)$(bindir) 90 | install -m 0755 pig2vcd $(DESTDIR)$(bindir) 91 | install -m 0755 pigpiod $(DESTDIR)$(bindir) 92 | install -m 0755 pigs $(DESTDIR)$(bindir) 93 | if which python2; then python2 setup.py install; fi 94 | if which python3; then python3 setup.py install; fi 95 | install -m 0755 -d $(DESTDIR)$(mandir)/man1 96 | install -m 0644 *.1 $(DESTDIR)$(mandir)/man1 97 | install -m 0755 -d $(DESTDIR)$(mandir)/man3 98 | install -m 0644 *.3 $(DESTDIR)$(mandir)/man3 99 | ldconfig 100 | 101 | uninstall: 102 | rm -f $(DESTDIR)$(includedir)/pigpio.h 103 | rm -f $(DESTDIR)$(includedir)/pigpiod_if.h 104 | rm -f $(DESTDIR)$(includedir)/pigpiod_if2.h 105 | rm -f $(DESTDIR)$(libdir)/libpigpio.so 106 | rm -f $(DESTDIR)$(libdir)/libpigpiod_if.so 107 | rm -f $(DESTDIR)$(libdir)/libpigpiod_if2.so 108 | rm -f $(DESTDIR)$(bindir)/pig2vcd 109 | rm -f $(DESTDIR)$(bindir)/pigpiod 110 | rm -f $(DESTDIR)$(bindir)/pigs 111 | if which python2; then python2 setup.py install --record /tmp/pigpio >/dev/null; xargs rm -f < /tmp/pigpio >/dev/null; fi 112 | if which python3; then python3 setup.py install --record /tmp/pigpio >/dev/null; xargs rm -f < /tmp/pigpio >/dev/null; fi 113 | rm -f $(DESTDIR)$(mandir)/man1/pig*.1 114 | rm -f $(DESTDIR)$(mandir)/man3/pig*.3 115 | ldconfig 116 | 117 | $(LIB1): $(OBJ1) 118 | $(SHLIB) -o $(LIB1) $(OBJ1) 119 | $(STRIPLIB) $(LIB1) 120 | $(SIZE) $(LIB1) 121 | 122 | $(LIB2): $(OBJ2) 123 | $(SHLIB) -o $(LIB2) $(OBJ2) 124 | $(STRIPLIB) $(LIB2) 125 | $(SIZE) $(LIB2) 126 | 127 | $(LIB3): $(OBJ3) 128 | $(SHLIB) -o $(LIB3) $(OBJ3) 129 | $(STRIPLIB) $(LIB3) 130 | $(SIZE) $(LIB3) 131 | 132 | # generated using gcc -MM *.c 133 | 134 | pig2vcd.o: pig2vcd.c pigpio.h 135 | pigpiod.o: pigpiod.c pigpio.h 136 | pigs.o: pigs.c pigpio.h command.h 137 | x_pigpio.o: x_pigpio.c pigpio.h 138 | x_pigpiod_if.o: x_pigpiod_if.c pigpiod_if.h pigpio.h 139 | x_pigpiod_if2.o: x_pigpiod_if2.c pigpiod_if2.h pigpio.h 140 | 141 | -------------------------------------------------------------------------------- /PIGPIO/README: -------------------------------------------------------------------------------- 1 | NOTE 2 | 3 | The initial part of the make, the compilation of pigpio.c, 4 | takes 100 seconds on early model Pis. Be patient. The overall 5 | install takes just over 3 minutes. 6 | 7 | INSTALL 8 | 9 | Extract the archive to a directory. 10 | 11 | IN THAT DIRECTORY 12 | 13 | Enter the following two commands (in this order) 14 | 15 | make 16 | sudo make install 17 | 18 | This will install 19 | 20 | o the library (libpigpio.so) in /usr/local/lib 21 | o the library (libpigpiod_if.so) in /usr/local/lib 22 | o the library (libpigpiod_if2.so) in /usr/local/lib 23 | o the header file (pigpio.h) in /usr/local/include 24 | o the header file (pigpiod_if.h) in /usr/local/include 25 | o the header file (pigpiod_if2.h) in /usr/local/include 26 | o the daemon (pigpiod) in /usr/local/bin 27 | o the socket interface (pigs) in /usr/local/bin 28 | o the utility pig2vcd in /usr/local/bin 29 | o man pages in /usr/local/man/man1 and /usr/local/man/man3 30 | o the Python module pigpio.py for Python 2 and 3 31 | 32 | TEST (optional) 33 | 34 | *** WARNING ************************************************ 35 | * * 36 | * All the tests make extensive use of gpio 4 (pin P1/J8-7).* 37 | * Ensure that either nothing or just a LED is connected to * 38 | * gpio 4 before running any of the tests. * 39 | * * 40 | * Some tests are statistical in nature and so may on * 41 | * occasion fail. Repeated failures on the same test or * 42 | * many failures in a group of tests indicate a problem. * 43 | ************************************************************ 44 | 45 | To test the library do 46 | 47 | sudo ./x_pigpio 48 | 49 | To test the pigpio daemon do 50 | 51 | sudo pigpiod 52 | 53 | ./x_pigpiod_if # test the C I/F to the pigpio daemon 54 | ./x_pigpiod_if2 # test the C I/F to the pigpio daemon 55 | ./x_pigpio.py # test the Python I/F to the pigpio daemon 56 | ./x_pigs # test the socket I/F to the pigpio daemon 57 | ./x_pipe # test the pipe I/F to the pigpio daemon 58 | 59 | EXAMPLE CODE 60 | 61 | x_pigpio.c, pig2vcd.c, and pigpiod.c show examples of interfacing 62 | with the pigpio library. 63 | 64 | pigs.c, pigpio.py, x_pigpiod_if, x_pigpiod_if2.c, x_pigpio.py, 65 | x_pigs, and x_pipe show examples of interfacing with the pigpio 66 | daemon. x_pipe uses the pipe interface, the others use the 67 | socket interface. 68 | 69 | DAEMON 70 | 71 | To launch the daemon do 72 | 73 | sudo pigpiod (pigpiod -? for options) 74 | 75 | Once the daemon is launched the socket and pipe interfaces will be 76 | available. 77 | 78 | When the library starts it locks 79 | 80 | /var/run/pigpio.pid 81 | 82 | The file should be automatically deleted when the library terminates. 83 | 84 | SOCKET INTERFACE 85 | 86 | Use pigs for the socket interface (pigs help for help). 87 | 88 | PIPE INTERFACE 89 | 90 | The pipe interface accepts commands written to /dev/pigpio. 91 | 92 | Results are read from /dev/pigout. 93 | 94 | Errors are output on /dev/pigerr. 95 | 96 | To test the pipe interface perhaps do 97 | 98 | cat /dev/pigout & 99 | cat /dev/pigerr & 100 | 101 | echo "help" >/dev/pigpio 102 | 103 | PYTHON MODULE 104 | 105 | The Python pigpio module is installed to the default Python location 106 | for Python 2 and Python 3. 107 | 108 | You can install it for additional Python versions by 109 | 110 | pythonx.y setup.py install 111 | 112 | where x.y is the Python version. 113 | 114 | STOP DAEMON 115 | 116 | To stop the pigpiod daemon 117 | 118 | sudo killall pigpiod 119 | 120 | RUNNING ON NON Pi's 121 | 122 | You can access the pigpiod daemon running on the Pi from any machine which 123 | is connected to it over the network. This access is via the socket interface. 124 | 125 | In particular this allows you to use the following on non-Pi's. 126 | 127 | o pigs 128 | o the pigpio Python module 129 | o the C socket I/F using libpigpiod_if (header file pigpiod_if.h) 130 | o the C socket I/F using libpigpiod_if2 (header file pigpiod_if2.h) 131 | 132 | On a Linux machine 133 | 134 | make -f MakeRemote clean 135 | make -f MakeRemote 136 | make -f MakeRemote install 137 | 138 | This will install 139 | 140 | o the library (libpigpiod_if.so) in /usr/local/lib 141 | o the library (libpigpiod_if2.so) in /usr/local/lib 142 | o the header file (pigpio.h) in /usr/local/include 143 | o the header file (pigpiod_if.h) in /usr/local/include 144 | o the header file (pigpiod_if2.h) in /usr/local/include 145 | o the socket interface (pigs) in /usr/local/bin 146 | o man pages in /usr/local/man/man1 and /usr/local/man/man3 147 | o the Python module pigpio.py 148 | 149 | On Windows machines (and possibly Macs) 150 | 151 | The Python module should install with 152 | 153 | python setup.py install 154 | 155 | pigs, pigpiod_if, and pigpiod_if2 will need minor mods to 156 | reflect the Windows/Mac socket interface. 157 | 158 | DOCUMENTATION 159 | 160 | The most up to date should be http://abyz.co.uk/rpi/pigpio/ 161 | 162 | On the Pi try 163 | 164 | man pigs 165 | man pigpiod 166 | man pig2vcd 167 | 168 | man pigpio 169 | man pigpiod_if 170 | man pigpiod_if2 171 | 172 | pydoc pigpio 173 | 174 | -------------------------------------------------------------------------------- /PIGPIO/UNLICENCE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | 26 | -------------------------------------------------------------------------------- /PIGPIO/command.h: -------------------------------------------------------------------------------- 1 | /* 2 | This is free and unencumbered software released into the public domain. 3 | 4 | Anyone is free to copy, modify, publish, use, compile, sell, or 5 | distribute this software, either in source code form or as a compiled 6 | binary, for any purpose, commercial or non-commercial, and by any 7 | means. 8 | 9 | In jurisdictions that recognize copyright laws, the author or authors 10 | of this software dedicate any and all copyright interest in the 11 | software to the public domain. We make this dedication for the benefit 12 | of the public at large and to the detriment of our heirs and 13 | successors. We intend this dedication to be an overt act of 14 | relinquishment in perpetuity of all present and future rights to this 15 | software under copyright law. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | For more information, please refer to 26 | */ 27 | 28 | /* 29 | This version is for pigpio version 57+ 30 | */ 31 | 32 | #ifndef COMMAND_H 33 | #define COMMAND_H 34 | 35 | #include 36 | #include 37 | 38 | #include "pigpio.h" 39 | 40 | #define CMD_MAX_PARAM 512 41 | #define CMD_MAX_EXTENSION (1<<16) 42 | 43 | #define CMD_UNKNOWN_CMD -1 44 | #define CMD_BAD_PARAMETER -2 45 | #define CMD_EXT_TOO_SMALL -3 46 | 47 | #define CMD_P_ARR 10 48 | #define CMD_V_ARR 10 49 | 50 | #define CMD_NUMERIC 1 51 | #define CMD_VAR 2 52 | #define CMD_PAR 3 53 | 54 | typedef struct 55 | { 56 | uint32_t cmd; 57 | uint32_t p1; 58 | uint32_t p2; 59 | union 60 | { 61 | uint32_t p3; 62 | uint32_t ext_len; 63 | uint32_t res; 64 | }; 65 | } cmdCmd_t; 66 | 67 | typedef struct 68 | { 69 | int eaten; 70 | int8_t opt[4]; 71 | } cmdCtlParse_t; 72 | 73 | typedef struct 74 | { 75 | int cmd; /* command number */ 76 | char *name; /* command name */ 77 | int vt; /* command verification type */ 78 | int rv; /* command return value type */ 79 | } cmdInfo_t; 80 | 81 | typedef struct 82 | { 83 | uint32_t tag; 84 | int step; 85 | } cmdTagStep_t; 86 | 87 | typedef struct 88 | { 89 | uint32_t p[5]; 90 | int8_t opt[4]; 91 | } cmdInstr_t; 92 | 93 | typedef struct 94 | { 95 | /* 96 | +-----------+---------+---------+----------------+ 97 | | PARAMS... | VARS... | CMDS... | STRING AREA... | 98 | +-----------+---------+---------+----------------+ 99 | */ 100 | int *par; 101 | int *var; 102 | cmdInstr_t *instr; 103 | int instrs; 104 | char *str_area; 105 | int str_area_len; 106 | int str_area_pos; 107 | } cmdScript_t; 108 | 109 | extern cmdInfo_t cmdInfo[]; 110 | 111 | extern char *cmdUsage; 112 | 113 | int cmdParse(char *buf, uint32_t *p, unsigned ext_len, char *ext, cmdCtlParse_t *ctl); 114 | 115 | int cmdParseScript(char *script, cmdScript_t *s, int diags); 116 | 117 | char *cmdErrStr(int error); 118 | 119 | char *cmdStr(void); 120 | 121 | #endif 122 | 123 | -------------------------------------------------------------------------------- /PIGPIO/command.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketrebilcock/js-gpiozero/8d02c3b65604cdd34a0f5ce7c8f905647237dc21/PIGPIO/command.o -------------------------------------------------------------------------------- /PIGPIO/custom.cext: -------------------------------------------------------------------------------- 1 | /* 2 | This version is for pigpio version 26+ 3 | 4 | If you want customised functions replace this file with your own 5 | definitions for gpioCustom1 and gpioCustom2. 6 | */ 7 | 8 | #include "pigpio.h" 9 | 10 | int gpioCustom1(unsigned arg1, unsigned arg2, char *argx, unsigned count) 11 | { 12 | int i; 13 | unsigned max; 14 | 15 | DBG(DBG_USER, "arg1=%d arg2=%d count=%d [%s]", 16 | arg1, arg2, count, myBuf2Str(count, argx)); 17 | 18 | CHECK_INITED; 19 | 20 | /* for dummy just return max parameter */ 21 | 22 | if (arg1 > arg2) max = arg1; else max = arg2; 23 | 24 | for (i=0; i max) max = argx[i]; 25 | 26 | return max; 27 | } 28 | 29 | 30 | int gpioCustom2(unsigned arg1, char *argx, unsigned count, 31 | char *retBuf, unsigned retMax) 32 | { 33 | int i, j, t; 34 | 35 | DBG(DBG_USER, "arg1=%d count=%d [%s] retMax=%d", 36 | arg1, count, myBuf2Str(count, argx), retMax); 37 | 38 | CHECK_INITED; 39 | 40 | /* for dummy just return argx reversed */ 41 | 42 | if (count > retMax) count = retMax; 43 | 44 | for (i=0, j=count-1; i<=j; i++, j--) 45 | { 46 | /* t used as argx and retBuf may be the same buffer */ 47 | t = argx[i]; 48 | retBuf[i] = argx[j]; 49 | retBuf[j] = t; 50 | } 51 | 52 | return count; 53 | } 54 | 55 | -------------------------------------------------------------------------------- /PIGPIO/libpigpio.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketrebilcock/js-gpiozero/8d02c3b65604cdd34a0f5ce7c8f905647237dc21/PIGPIO/libpigpio.so -------------------------------------------------------------------------------- /PIGPIO/libpigpiod_if.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketrebilcock/js-gpiozero/8d02c3b65604cdd34a0f5ce7c8f905647237dc21/PIGPIO/libpigpiod_if.so -------------------------------------------------------------------------------- /PIGPIO/libpigpiod_if2.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketrebilcock/js-gpiozero/8d02c3b65604cdd34a0f5ce7c8f905647237dc21/PIGPIO/libpigpiod_if2.so -------------------------------------------------------------------------------- /PIGPIO/pig2vcd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketrebilcock/js-gpiozero/8d02c3b65604cdd34a0f5ce7c8f905647237dc21/PIGPIO/pig2vcd -------------------------------------------------------------------------------- /PIGPIO/pig2vcd.1: -------------------------------------------------------------------------------- 1 | 2 | ." Process this file with 3 | ." groff -man -Tascii pig2vcd.1 4 | ." 5 | .TH pig2vcd 1 2012-2015 Linux "pigpio archive" 6 | .SH NAME 7 | pig2vd - A utility to convert pigpio notifications to VCD. 8 | 9 | .SH SYNOPSIS 10 | 11 | pig2vcd file.VCD 12 | .SH DESCRIPTION 13 | 14 | 15 | .ad l 16 | 17 | .nh 18 | pig2vcd is a utility which reads notifications on stdin and writes the 19 | output as a Value Change Dump (VCD) file on stdout. 20 | 21 | .br 22 | 23 | .br 24 | The VCD file can be viewed using GTKWave. 25 | 26 | .br 27 | 28 | .br 29 | .SS Notifications 30 | .br 31 | 32 | .br 33 | Notifications consist of 12 bytes with the following binary format. 34 | 35 | .br 36 | 37 | .br 38 | 39 | .EX 40 | typedef struct 41 | .br 42 | { 43 | .br 44 | uint16_t seqno; 45 | .br 46 | uint16_t flags; 47 | .br 48 | uint32_t tick; 49 | .br 50 | uint32_t level; 51 | .br 52 | } gpioReport_t; 53 | .br 54 | 55 | .EE 56 | 57 | .br 58 | 59 | .br 60 | seqno: starts at 0 each time the handle is opened and then increments by one for each report. 61 | 62 | .br 63 | 64 | .br 65 | flags: two flags are defined, PI_NTFY_FLAGS_WDOG and PI_NTFY_FLAGS_ALIVE. If bit 5 is set (PI_NTFY_FLAGS_WDOG) then bits 0-4 of the flags indicate a gpio which has had a watchdog timeout; if bit 6 is set (PI_NTFY_FLAGS_ALIVE) this indicates a keep alive signal on the pipe/socket and is sent once a minute in the absence of other notification activity. 66 | 67 | .br 68 | 69 | .br 70 | tick: the number of microseconds since system boot. It wraps around after 1h12m. 71 | 72 | .br 73 | 74 | .br 75 | level: indicates the level of each gpio. If bit 1< 26 | */ 27 | 28 | /* 29 | This version is for pigpio version 3+ 30 | */ 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #include "pigpio.h" 43 | 44 | /* 45 | This software converts pigpio notification reports 46 | into a VCD format understood by GTKWave. 47 | */ 48 | 49 | #define RS (sizeof(gpioReport_t)) 50 | 51 | static char * timeStamp() 52 | { 53 | static char buf[32]; 54 | 55 | struct timeval now; 56 | struct tm tmp; 57 | 58 | gettimeofday(&now, NULL); 59 | 60 | localtime_r(&now.tv_sec, &tmp); 61 | strftime(buf, sizeof(buf), "%F %T", &tmp); 62 | 63 | return buf; 64 | } 65 | 66 | int symbol(int bit) 67 | { 68 | if (bit < 26) return ('A' + bit); 69 | else return ('a' + bit - 26); 70 | } 71 | 72 | int main(int argc, char * argv[]) 73 | { 74 | int b, r, v; 75 | uint32_t t0; 76 | uint32_t lastLevel, changed; 77 | 78 | gpioReport_t report; 79 | 80 | r=read(STDIN_FILENO, &report, RS); 81 | 82 | if (r != RS) exit(-1); 83 | 84 | printf("$date %s $end\n", timeStamp()); 85 | printf("$version pig2vcd V1 $end\n"); 86 | printf("$timescale 1 us $end\n"); 87 | printf("$scope module top $end\n"); 88 | 89 | for (b=0; b<32; b++) 90 | printf("$var wire 1 %c %d $end\n", symbol(b), b); 91 | 92 | printf("$upscope $end\n"); 93 | printf("$enddefinitions $end\n"); 94 | 95 | t0 = report.tick; 96 | lastLevel =0; 97 | 98 | while ((r=read(STDIN_FILENO, &report, RS)) == RS) 99 | { 100 | if (report.level != lastLevel) 101 | { 102 | printf("#%u\n", report.tick - t0); 103 | 104 | changed = report.level ^ lastLevel; 105 | 106 | lastLevel = report.level; 107 | 108 | for (b=0; b<32; b++) 109 | { 110 | if (changed & (1< 26 | */ 27 | 28 | /* 29 | This version is for pigpio version 56+ 30 | */ 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | #include "pigpio.h" 44 | #include "command.h" 45 | 46 | /* 47 | This program provides a socket interface to some of 48 | the commands available from pigpio. 49 | */ 50 | 51 | char command_buf[CMD_MAX_EXTENSION]; 52 | char response_buf[CMD_MAX_EXTENSION]; 53 | 54 | int printFlags = 0; 55 | 56 | #define SOCKET_OPEN_FAILED -1 57 | 58 | #define PRINT_HEX 1 59 | #define PRINT_ASCII 2 60 | 61 | void fatal(char *fmt, ...) 62 | { 63 | char buf[128]; 64 | va_list ap; 65 | 66 | va_start(ap, fmt); 67 | vsnprintf(buf, sizeof(buf), fmt, ap); 68 | va_end(ap); 69 | 70 | fprintf(stderr, "%s\n", buf); 71 | 72 | fflush(stderr); 73 | } 74 | 75 | static int initOpts(int argc, char *argv[]) 76 | { 77 | int opt, args; 78 | 79 | args = 1; 80 | 81 | while ((opt = getopt(argc, argv, "ax")) != -1) 82 | { 83 | switch (opt) 84 | { 85 | case 'a': 86 | printFlags |= PRINT_ASCII; 87 | args++; 88 | break; 89 | 90 | case 'x': 91 | printFlags |= PRINT_HEX; 92 | args++; 93 | break; 94 | } 95 | } 96 | return args; 97 | } 98 | 99 | static int openSocket(void) 100 | { 101 | int sock, err; 102 | struct addrinfo hints, *res, *rp; 103 | const char *addrStr, *portStr; 104 | 105 | portStr = getenv(PI_ENVPORT); 106 | 107 | if (!portStr) portStr = PI_DEFAULT_SOCKET_PORT_STR; 108 | 109 | addrStr = getenv(PI_ENVADDR); 110 | 111 | if (!addrStr) addrStr = PI_DEFAULT_SOCKET_ADDR_STR; 112 | 113 | memset (&hints, 0, sizeof (hints)); 114 | 115 | hints.ai_family = PF_UNSPEC; 116 | hints.ai_socktype = SOCK_STREAM; 117 | hints.ai_flags |= AI_CANONNAME; 118 | 119 | err = getaddrinfo(addrStr, portStr, &hints, &res); 120 | 121 | if (err) return SOCKET_OPEN_FAILED; 122 | 123 | for (rp=res; rp!=NULL; rp=rp->ai_next) 124 | { 125 | sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); 126 | 127 | if (sock == -1) continue; 128 | 129 | if (connect(sock, rp->ai_addr, rp->ai_addrlen) != -1) break; 130 | } 131 | 132 | freeaddrinfo(res); 133 | 134 | if (rp == NULL) return SOCKET_OPEN_FAILED; 135 | 136 | return sock; 137 | } 138 | 139 | void print_result(int sock, int rv, cmdCmd_t cmd) 140 | { 141 | int i, r, ch; 142 | uint32_t *p; 143 | 144 | r = cmd.res; 145 | 146 | switch (rv) 147 | { 148 | case 0: 149 | case 1: 150 | if (r < 0) 151 | { 152 | printf("%d\n", r); 153 | fatal("ERROR: %s", cmdErrStr(r)); 154 | } 155 | break; 156 | 157 | case 2: 158 | printf("%d\n", r); 159 | if (r < 0) fatal("ERROR: %s", cmdErrStr(r)); 160 | break; 161 | 162 | case 3: 163 | printf("%08X\n", cmd.res); 164 | break; 165 | 166 | case 4: 167 | printf("%u\n", cmd.res); 168 | break; 169 | 170 | case 5: 171 | printf("%s", cmdUsage); 172 | break; 173 | 174 | case 6: /* 175 | BI2CZ CF2 FL FR I2CPK I2CRD I2CRI I2CRK 176 | I2CZ SERR SLR SPIX SPIR 177 | */ 178 | printf("%d", r); 179 | if (r < 0) fatal("ERROR: %s", cmdErrStr(r)); 180 | if (r > 0) 181 | { 182 | if (printFlags == PRINT_ASCII) printf(" "); 183 | 184 | for (i=0; i 4) 233 | { 234 | if (printFlags == PRINT_ASCII) printf(" "); 235 | 236 | for (i=4; i 0) 279 | { 280 | recv(sock, response_buf, res, MSG_WAITALL); 281 | response_buf[res] = 0; 282 | } 283 | break; 284 | } 285 | } 286 | 287 | int main(int argc , char *argv[]) 288 | { 289 | int sock, command; 290 | int args, idx, i, pp, l, len; 291 | cmdCmd_t cmd; 292 | uint32_t p[CMD_P_ARR]; 293 | cmdCtlParse_t ctl; 294 | cmdScript_t s; 295 | char v[CMD_MAX_EXTENSION]; 296 | 297 | sock = openSocket(); 298 | 299 | args = initOpts(argc, argv); 300 | 301 | command_buf[0] = 0; 302 | l = 0; 303 | pp = 0; 304 | 305 | for (i=args; i= 0) && (ctl.eaten < len)) 320 | { 321 | if ((idx=cmdParse(command_buf, p, CMD_MAX_EXTENSION, v, &ctl)) >= 0) 322 | { 323 | command = p[0]; 324 | 325 | if (command < PI_CMD_SCRIPT) 326 | { 327 | if (command == PI_CMD_HELP) 328 | { 329 | printf("%s", cmdUsage); 330 | } 331 | else if (command == PI_CMD_PARSE) 332 | { 333 | cmdParseScript(v, &s, 1); 334 | if (s.par) free (s.par); 335 | } 336 | else 337 | { 338 | cmd.cmd = command; 339 | cmd.p1 = p[1]; 340 | cmd.p2 = p[2]; 341 | cmd.p3 = p[3]; 342 | 343 | if (sock != SOCKET_OPEN_FAILED) 344 | { 345 | if (send(sock, &cmd, sizeof(cmdCmd_t), 0) == 346 | sizeof(cmdCmd_t)) 347 | { 348 | if (p[3]) send(sock, v, p[3], 0); /* send extensions */ 349 | 350 | if (recv(sock, &cmd, sizeof(cmdCmd_t), MSG_WAITALL) == 351 | sizeof(cmdCmd_t)) 352 | { 353 | get_extensions(sock, command, cmd.res); 354 | 355 | print_result(sock, cmdInfo[idx].rv, cmd); 356 | } 357 | else fatal("socket receive failed"); 358 | } 359 | else fatal("socket send failed"); 360 | } 361 | else fatal("socket connect failed"); 362 | } 363 | } 364 | else fatal("%s only allowed within a script", cmdInfo[idx].name); 365 | } 366 | else 367 | { 368 | if (idx == CMD_UNKNOWN_CMD) 369 | fatal("%s? unknown command, pigs h for help", cmdStr()); 370 | else 371 | fatal("%s: bad parameter, pigs h for help", cmdStr()); 372 | } 373 | } 374 | 375 | if (sock >= 0) close(sock); 376 | 377 | return 0; 378 | } 379 | 380 | -------------------------------------------------------------------------------- /PIGPIO/pigs.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketrebilcock/js-gpiozero/8d02c3b65604cdd34a0f5ce7c8f905647237dc21/PIGPIO/pigs.o -------------------------------------------------------------------------------- /PIGPIO/setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from distutils.core import setup 4 | 5 | setup(name='pigpio', 6 | version='1.35', 7 | author='joan', 8 | author_email='joan@abyz.co.uk', 9 | maintainer='joan', 10 | maintainer_email='joan@abyz.co.uk', 11 | url='http://abyz.co.uk/rpi/pigpio/python.html/', 12 | description='Raspberry gpio module', 13 | long_description='Raspberry Python module to access the pigpio daemon', 14 | download_url='http://abyz.co.uk/rpi/pigpio/pigpio.zip', 15 | license='unlicense.org', 16 | py_modules=['pigpio'] 17 | ) 18 | -------------------------------------------------------------------------------- /PIGPIO/x_pigpio: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketrebilcock/js-gpiozero/8d02c3b65604cdd34a0f5ce7c8f905647237dc21/PIGPIO/x_pigpio -------------------------------------------------------------------------------- /PIGPIO/x_pigpio.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketrebilcock/js-gpiozero/8d02c3b65604cdd34a0f5ce7c8f905647237dc21/PIGPIO/x_pigpio.o -------------------------------------------------------------------------------- /PIGPIO/x_pigpiod_if: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketrebilcock/js-gpiozero/8d02c3b65604cdd34a0f5ce7c8f905647237dc21/PIGPIO/x_pigpiod_if -------------------------------------------------------------------------------- /PIGPIO/x_pigpiod_if.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketrebilcock/js-gpiozero/8d02c3b65604cdd34a0f5ce7c8f905647237dc21/PIGPIO/x_pigpiod_if.o -------------------------------------------------------------------------------- /PIGPIO/x_pigpiod_if2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketrebilcock/js-gpiozero/8d02c3b65604cdd34a0f5ce7c8f905647237dc21/PIGPIO/x_pigpiod_if2 -------------------------------------------------------------------------------- /PIGPIO/x_pigpiod_if2.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketrebilcock/js-gpiozero/8d02c3b65604cdd34a0f5ce7c8f905647237dc21/PIGPIO/x_pigpiod_if2.o -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # js-gpiozero 2 | 3 | [![Build Tests](https://travis-ci.org/miketrebilcock/js-gpiozero.svg?branch=master)](https://travis-ci.org/miketrebilcock/js-gpiozero) [![Code Coverage](https://codecov.io/gh/miketrebilcock/js-gpiozero/branch/master/graph/badge.svg)](https://codecov.io/gh/miketrebilcock/js-gpiozero) [![npm version](https://badge.fury.io/js/js-gpiozero.svg)](https://badge.fury.io/js/js-gpiozero) [![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release) 4 | 5 | A port of the fanastic [python gpiozero](https://github.com/RPi-Distro/python-gpiozero) to javascript creating simple interface to everyday GPIO components used with Raspberry Pi on node.js. 6 | 7 | It's early days and a work in progress! 8 | 9 | ## Documentation 10 | The API Documentation is available at the repos [github-pages](https://miketrebilcock.github.io/js-gpiozero/). 11 | 12 | ## Using 13 | First of all we need to be running the latest version of nodejs (at least v6). The following command updates the Debian apt package repository to include the NodeSource packages 14 | 15 | ```bash 16 | $curl -sL https://deb.nodesource.com/setup_7.x | sudo -E bash - 17 | ``` 18 | 19 | Now that we have added the NodeSource package repository, we can move on and install Node.js! 20 | 21 | ```bash 22 | $ sudo apt install nodejs 23 | ``` 24 | 25 | We can then test and see what version of Node we are running 26 | 27 | ```bash 28 | $ node -v 29 | v7.3.0 30 | 31 | ``` 32 | 33 | ## Contributing [![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/miketrebilcock/js-gpiozero/issues) [![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/) 34 | 35 | The project is very much a work in progress. Some far the output part of gpiozero has been followed through, completing a near direct translation from the original Python. This means the operating model hasn't really taken advantage of the nodejs programming paradigm. That's next! It's mostly written in EMCAScript 5 with a splash of 6, the intention is to written everything in 6, then use babel to create an output that nodejs can use. The projects tab shows current work, planned and in progress, feel free to pick up a task and have a go. 36 | 37 | The documentation is produced by [jsdoc](https://www.npmjs.com/package/jsdoc), enabling the api documentation to be written within the source code. Upon committing to git, a pre-commit task will run, this runs all tests and updates the documentation. Checkout [Git Hooks](https://www.atlassian.com/git/tutorials/git-hooks/local-hooks) for more info. 38 | 39 | To enable this the follow line needs to be executed: 40 | 41 | ```bash 42 | $ln -s ../../pre-commit.sh .git/hooks/pre-commit 43 | ``` 44 | 45 | or you can simply run the following command: 46 | 47 | ```bash 48 | $npm run docs 49 | ``` 50 | 51 | More info about contributing can be found [here](https://github.com/miketrebilcock/js-gpiozero/blob/master/CONTRIBUTING.md) 52 | 53 | [![NPM](https://nodei.co/npm/js-gpiozero.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/js-gpiozero/) 54 | 55 | -------------------------------------------------------------------------------- /docs/assets/anchor.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * AnchorJS - v1.2.1 - 2015-07-02 3 | * https://github.com/bryanbraun/anchorjs 4 | * Copyright (c) 2015 Bryan Braun; Licensed MIT 5 | */ 6 | 7 | function AnchorJS(options) { 8 | 'use strict'; 9 | 10 | this.options = options || {}; 11 | 12 | this._applyRemainingDefaultOptions = function(opts) { 13 | this.options.icon = this.options.hasOwnProperty('icon') ? opts.icon : '\ue9cb'; // Accepts characters (and also URLs?), like '#', '¶', '❡', or '§'. 14 | this.options.visible = this.options.hasOwnProperty('visible') ? opts.visible : 'hover'; // Also accepts 'always' 15 | this.options.placement = this.options.hasOwnProperty('placement') ? opts.placement : 'right'; // Also accepts 'left' 16 | this.options.class = this.options.hasOwnProperty('class') ? opts.class : ''; // Accepts any class name. 17 | }; 18 | 19 | this._applyRemainingDefaultOptions(options); 20 | 21 | this.add = function(selector) { 22 | var elements, 23 | elsWithIds, 24 | idList, 25 | elementID, 26 | i, 27 | roughText, 28 | tidyText, 29 | index, 30 | count, 31 | newTidyText, 32 | readableID, 33 | anchor; 34 | 35 | this._applyRemainingDefaultOptions(this.options); 36 | 37 | // Provide a sensible default selector, if none is given. 38 | if (!selector) { 39 | selector = 'h1, h2, h3, h4, h5, h6'; 40 | } else if (typeof selector !== 'string') { 41 | throw new Error('The selector provided to AnchorJS was invalid.'); 42 | } 43 | 44 | elements = document.querySelectorAll(selector); 45 | if (elements.length === 0) { 46 | return false; 47 | } 48 | 49 | this._addBaselineStyles(); 50 | 51 | // We produce a list of existing IDs so we don't generate a duplicate. 52 | elsWithIds = document.querySelectorAll('[id]'); 53 | idList = [].map.call(elsWithIds, function assign(el) { 54 | return el.id; 55 | }); 56 | 57 | for (i = 0; i < elements.length; i++) { 58 | 59 | if (elements[i].hasAttribute('id')) { 60 | elementID = elements[i].getAttribute('id'); 61 | } else { 62 | roughText = elements[i].textContent; 63 | 64 | // Refine it so it makes a good ID. Strip out non-safe characters, replace 65 | // spaces with hyphens, truncate to 32 characters, and make toLowerCase. 66 | // 67 | // Example string: // '⚡⚡⚡ Unicode icons are cool--but they definitely don't belong in a URL fragment.' 68 | tidyText = roughText.replace(/[^\w\s-]/gi, '') // ' Unicode icons are cool--but they definitely dont belong in a URL fragment' 69 | .replace(/\s+/g, '-') // '-Unicode-icons-are-cool--but-they-definitely-dont-belong-in-a-URL-fragment' 70 | .replace(/-{2,}/g, '-') // '-Unicode-icons-are-cool-but-they-definitely-dont-belong-in-a-URL-fragment' 71 | .substring(0, 64) // '-Unicode-icons-are-cool-but-they-definitely-dont-belong-in-a-URL' 72 | .replace(/^-+|-+$/gm, '') // 'Unicode-icons-are-cool-but-they-definitely-dont-belong-in-a-URL' 73 | .toLowerCase(); // 'unicode-icons-are-cool-but-they-definitely-dont-belong-in-a-url' 74 | 75 | // Compare our generated ID to existing IDs (and increment it if needed) 76 | // before we add it to the page. 77 | newTidyText = tidyText; 78 | count = 0; 79 | do { 80 | if (index !== undefined) { 81 | newTidyText = tidyText + '-' + count; 82 | } 83 | // .indexOf is supported in IE9+. 84 | index = idList.indexOf(newTidyText); 85 | count += 1; 86 | } while (index !== -1); 87 | index = undefined; 88 | idList.push(newTidyText); 89 | 90 | // Assign it to our element. 91 | // Currently the setAttribute element is only supported in IE9 and above. 92 | elements[i].setAttribute('id', newTidyText); 93 | 94 | elementID = newTidyText; 95 | } 96 | 97 | readableID = elementID.replace(/-/g, ' '); 98 | 99 | // The following code builds the following DOM structure in a more effiecient (albeit opaque) way. 100 | // ''; 101 | anchor = document.createElement('a'); 102 | anchor.className = 'anchorjs-link ' + this.options.class; 103 | anchor.href = '#' + elementID; 104 | anchor.setAttribute('aria-label', 'Anchor link for: ' + readableID); 105 | anchor.setAttribute('data-anchorjs-icon', this.options.icon); 106 | 107 | if (this.options.visible === 'always') { 108 | anchor.style.opacity = '1'; 109 | } 110 | 111 | if (this.options.icon === '\ue9cb') { 112 | anchor.style.fontFamily = 'anchorjs-icons'; 113 | anchor.style.fontStyle = 'normal'; 114 | anchor.style.fontVariant = 'normal'; 115 | anchor.style.fontWeight = 'normal'; 116 | anchor.style.lineHeight = 1; 117 | } 118 | 119 | if (this.options.placement === 'left') { 120 | anchor.style.position = 'absolute'; 121 | anchor.style.marginLeft = '-1em'; 122 | anchor.style.paddingRight = '0.5em'; 123 | elements[i].insertBefore(anchor, elements[i].firstChild); 124 | } else { // if the option provided is `right` (or anything else). 125 | anchor.style.paddingLeft = '0.375em'; 126 | elements[i].appendChild(anchor); 127 | } 128 | } 129 | 130 | return this; 131 | }; 132 | 133 | this.remove = function(selector) { 134 | var domAnchor, 135 | elements = document.querySelectorAll(selector); 136 | for (var i = 0; i < elements.length; i++) { 137 | domAnchor = elements[i].querySelector('.anchorjs-link'); 138 | if (domAnchor) { 139 | elements[i].removeChild(domAnchor); 140 | } 141 | } 142 | return this; 143 | }; 144 | 145 | this._addBaselineStyles = function() { 146 | // We don't want to add global baseline styles if they've been added before. 147 | if (document.head.querySelector('style.anchorjs') !== null) { 148 | return; 149 | } 150 | 151 | var style = document.createElement('style'), 152 | linkRule = 153 | ' .anchorjs-link {' + 154 | ' opacity: 0;' + 155 | ' text-decoration: none;' + 156 | ' -webkit-font-smoothing: antialiased;' + 157 | ' -moz-osx-font-smoothing: grayscale;' + 158 | ' }', 159 | hoverRule = 160 | ' *:hover > .anchorjs-link,' + 161 | ' .anchorjs-link:focus {' + 162 | ' opacity: 1;' + 163 | ' }', 164 | anchorjsLinkFontFace = 165 | ' @font-face {' + 166 | ' font-family: "anchorjs-icons";' + 167 | ' font-style: normal;' + 168 | ' font-weight: normal;' + // Icon from icomoon; 10px wide & 10px tall; 2 empty below & 4 above 169 | ' src: url(data:application/x-font-ttf;charset=utf-8;base64,AAEAAAALAIAAAwAwT1MvMg8SBTUAAAC8AAAAYGNtYXAWi9QdAAABHAAAAFRnYXNwAAAAEAAAAXAAAAAIZ2x5Zgq29TcAAAF4AAABNGhlYWQEZM3pAAACrAAAADZoaGVhBhUDxgAAAuQAAAAkaG10eASAADEAAAMIAAAAFGxvY2EAKACuAAADHAAAAAxtYXhwAAgAVwAAAygAAAAgbmFtZQ5yJ3cAAANIAAAB2nBvc3QAAwAAAAAFJAAAACAAAwJAAZAABQAAApkCzAAAAI8CmQLMAAAB6wAzAQkAAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAABAAADpywPA/8AAQAPAAEAAAAABAAAAAAAAAAAAAAAgAAAAAAADAAAAAwAAABwAAQADAAAAHAADAAEAAAAcAAQAOAAAAAoACAACAAIAAQAg6cv//f//AAAAAAAg6cv//f//AAH/4xY5AAMAAQAAAAAAAAAAAAAAAQAB//8ADwABAAAAAAAAAAAAAgAANzkBAAAAAAEAAAAAAAAAAAACAAA3OQEAAAAAAQAAAAAAAAAAAAIAADc5AQAAAAACADEARAJTAsAAKwBUAAABIiYnJjQ/AT4BMzIWFxYUDwEGIicmND8BNjQnLgEjIgYPAQYUFxYUBw4BIwciJicmND8BNjIXFhQPAQYUFx4BMzI2PwE2NCcmNDc2MhcWFA8BDgEjARQGDAUtLXoWOR8fORYtLTgKGwoKCjgaGg0gEhIgDXoaGgkJBQwHdR85Fi0tOAobCgoKOBoaDSASEiANehoaCQkKGwotLXoWOR8BMwUFLYEuehYXFxYugC44CQkKGwo4GkoaDQ0NDXoaShoKGwoFBe8XFi6ALjgJCQobCjgaShoNDQ0NehpKGgobCgoKLYEuehYXAAEAAAABAACiToc1Xw889QALBAAAAAAA0XnFFgAAAADRecUWAAAAAAJTAsAAAAAIAAIAAAAAAAAAAQAAA8D/wAAABAAAAAAAAlMAAQAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAACAAAAAoAAMQAAAAAACgAUAB4AmgABAAAABQBVAAIAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAADgCuAAEAAAAAAAEADgAAAAEAAAAAAAIABwCfAAEAAAAAAAMADgBLAAEAAAAAAAQADgC0AAEAAAAAAAUACwAqAAEAAAAAAAYADgB1AAEAAAAAAAoAGgDeAAMAAQQJAAEAHAAOAAMAAQQJAAIADgCmAAMAAQQJAAMAHABZAAMAAQQJAAQAHADCAAMAAQQJAAUAFgA1AAMAAQQJAAYAHACDAAMAAQQJAAoANAD4YW5jaG9yanMtaWNvbnMAYQBuAGMAaABvAHIAagBzAC0AaQBjAG8AbgBzVmVyc2lvbiAxLjAAVgBlAHIAcwBpAG8AbgAgADEALgAwYW5jaG9yanMtaWNvbnMAYQBuAGMAaABvAHIAagBzAC0AaQBjAG8AbgBzYW5jaG9yanMtaWNvbnMAYQBuAGMAaABvAHIAagBzAC0AaQBjAG8AbgBzUmVndWxhcgBSAGUAZwB1AGwAYQByYW5jaG9yanMtaWNvbnMAYQBuAGMAaABvAHIAagBzAC0AaQBjAG8AbgBzRm9udCBnZW5lcmF0ZWQgYnkgSWNvTW9vbi4ARgBvAG4AdAAgAGcAZQBuAGUAcgBhAHQAZQBkACAAYgB5ACAASQBjAG8ATQBvAG8AbgAuAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==) format("truetype");' + 170 | ' }', 171 | pseudoElContent = 172 | ' [data-anchorjs-icon]::after {' + 173 | ' content: attr(data-anchorjs-icon);' + 174 | ' }', 175 | firstStyleEl; 176 | 177 | style.className = 'anchorjs'; 178 | style.appendChild(document.createTextNode('')); // Necessary for Webkit. 179 | 180 | // We place it in the head with the other style tags, if possible, so as to 181 | // not look out of place. We insert before the others so these styles can be 182 | // overridden if necessary. 183 | firstStyleEl = document.head.querySelector('[rel="stylesheet"], style'); 184 | if (firstStyleEl === undefined) { 185 | document.head.appendChild(style); 186 | } else { 187 | document.head.insertBefore(style, firstStyleEl); 188 | } 189 | 190 | style.sheet.insertRule(linkRule, style.sheet.cssRules.length); 191 | style.sheet.insertRule(hoverRule, style.sheet.cssRules.length); 192 | style.sheet.insertRule(pseudoElContent, style.sheet.cssRules.length); 193 | style.sheet.insertRule(anchorjsLinkFontFace, style.sheet.cssRules.length); 194 | }; 195 | } 196 | 197 | var anchors = new AnchorJS(); 198 | -------------------------------------------------------------------------------- /docs/assets/bass-addons.css: -------------------------------------------------------------------------------- 1 | .input { 2 | font-family: inherit; 3 | display: block; 4 | width: 100%; 5 | height: 2rem; 6 | padding: .5rem; 7 | margin-bottom: 1rem; 8 | border: 1px solid #ccc; 9 | font-size: .875rem; 10 | border-radius: 3px; 11 | box-sizing: border-box; 12 | } 13 | -------------------------------------------------------------------------------- /docs/assets/fonts/EOT/SourceCodePro-Bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketrebilcock/js-gpiozero/8d02c3b65604cdd34a0f5ce7c8f905647237dc21/docs/assets/fonts/EOT/SourceCodePro-Bold.eot -------------------------------------------------------------------------------- /docs/assets/fonts/EOT/SourceCodePro-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketrebilcock/js-gpiozero/8d02c3b65604cdd34a0f5ce7c8f905647237dc21/docs/assets/fonts/EOT/SourceCodePro-Regular.eot -------------------------------------------------------------------------------- /docs/assets/fonts/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. 2 | 3 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 4 | 5 | This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL 6 | 7 | 8 | ----------------------------------------------------------- 9 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 10 | ----------------------------------------------------------- 11 | 12 | PREAMBLE 13 | The goals of the Open Font License (OFL) are to stimulate worldwide 14 | development of collaborative font projects, to support the font creation 15 | efforts of academic and linguistic communities, and to provide a free and 16 | open framework in which fonts may be shared and improved in partnership 17 | with others. 18 | 19 | The OFL allows the licensed fonts to be used, studied, modified and 20 | redistributed freely as long as they are not sold by themselves. The 21 | fonts, including any derivative works, can be bundled, embedded, 22 | redistributed and/or sold with any software provided that any reserved 23 | names are not used by derivative works. The fonts and derivatives, 24 | however, cannot be released under any other type of license. The 25 | requirement for fonts to remain under this license does not apply 26 | to any document created using the fonts or their derivatives. 27 | 28 | DEFINITIONS 29 | "Font Software" refers to the set of files released by the Copyright 30 | Holder(s) under this license and clearly marked as such. This may 31 | include source files, build scripts and documentation. 32 | 33 | "Reserved Font Name" refers to any names specified as such after the 34 | copyright statement(s). 35 | 36 | "Original Version" refers to the collection of Font Software components as 37 | distributed by the Copyright Holder(s). 38 | 39 | "Modified Version" refers to any derivative made by adding to, deleting, 40 | or substituting -- in part or in whole -- any of the components of the 41 | Original Version, by changing formats or by porting the Font Software to a 42 | new environment. 43 | 44 | "Author" refers to any designer, engineer, programmer, technical 45 | writer or other person who contributed to the Font Software. 46 | 47 | PERMISSION & CONDITIONS 48 | Permission is hereby granted, free of charge, to any person obtaining 49 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 50 | redistribute, and sell modified and unmodified copies of the Font 51 | Software, subject to the following conditions: 52 | 53 | 1) Neither the Font Software nor any of its individual components, 54 | in Original or Modified Versions, may be sold by itself. 55 | 56 | 2) Original or Modified Versions of the Font Software may be bundled, 57 | redistributed and/or sold with any software, provided that each copy 58 | contains the above copyright notice and this license. These can be 59 | included either as stand-alone text files, human-readable headers or 60 | in the appropriate machine-readable metadata fields within text or 61 | binary files as long as those fields can be easily viewed by the user. 62 | 63 | 3) No Modified Version of the Font Software may use the Reserved Font 64 | Name(s) unless explicit written permission is granted by the corresponding 65 | Copyright Holder. This restriction only applies to the primary font name as 66 | presented to the users. 67 | 68 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 69 | Software shall not be used to promote, endorse or advertise any 70 | Modified Version, except to acknowledge the contribution(s) of the 71 | Copyright Holder(s) and the Author(s) or with their explicit written 72 | permission. 73 | 74 | 5) The Font Software, modified or unmodified, in part or in whole, 75 | must be distributed entirely under this license, and must not be 76 | distributed under any other license. The requirement for fonts to 77 | remain under this license does not apply to any document created 78 | using the Font Software. 79 | 80 | TERMINATION 81 | This license becomes null and void if any of the above conditions are 82 | not met. 83 | 84 | DISCLAIMER 85 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 86 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 87 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 88 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 89 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 90 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 91 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 92 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 93 | OTHER DEALINGS IN THE FONT SOFTWARE. 94 | -------------------------------------------------------------------------------- /docs/assets/fonts/OTF/SourceCodePro-Bold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketrebilcock/js-gpiozero/8d02c3b65604cdd34a0f5ce7c8f905647237dc21/docs/assets/fonts/OTF/SourceCodePro-Bold.otf -------------------------------------------------------------------------------- /docs/assets/fonts/OTF/SourceCodePro-Regular.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketrebilcock/js-gpiozero/8d02c3b65604cdd34a0f5ce7c8f905647237dc21/docs/assets/fonts/OTF/SourceCodePro-Regular.otf -------------------------------------------------------------------------------- /docs/assets/fonts/TTF/SourceCodePro-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketrebilcock/js-gpiozero/8d02c3b65604cdd34a0f5ce7c8f905647237dc21/docs/assets/fonts/TTF/SourceCodePro-Bold.ttf -------------------------------------------------------------------------------- /docs/assets/fonts/TTF/SourceCodePro-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketrebilcock/js-gpiozero/8d02c3b65604cdd34a0f5ce7c8f905647237dc21/docs/assets/fonts/TTF/SourceCodePro-Regular.ttf -------------------------------------------------------------------------------- /docs/assets/fonts/WOFF/OTF/SourceCodePro-Bold.otf.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketrebilcock/js-gpiozero/8d02c3b65604cdd34a0f5ce7c8f905647237dc21/docs/assets/fonts/WOFF/OTF/SourceCodePro-Bold.otf.woff -------------------------------------------------------------------------------- /docs/assets/fonts/WOFF/OTF/SourceCodePro-Regular.otf.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketrebilcock/js-gpiozero/8d02c3b65604cdd34a0f5ce7c8f905647237dc21/docs/assets/fonts/WOFF/OTF/SourceCodePro-Regular.otf.woff -------------------------------------------------------------------------------- /docs/assets/fonts/WOFF/TTF/SourceCodePro-Bold.ttf.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketrebilcock/js-gpiozero/8d02c3b65604cdd34a0f5ce7c8f905647237dc21/docs/assets/fonts/WOFF/TTF/SourceCodePro-Bold.ttf.woff -------------------------------------------------------------------------------- /docs/assets/fonts/WOFF/TTF/SourceCodePro-Regular.ttf.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketrebilcock/js-gpiozero/8d02c3b65604cdd34a0f5ce7c8f905647237dc21/docs/assets/fonts/WOFF/TTF/SourceCodePro-Regular.ttf.woff -------------------------------------------------------------------------------- /docs/assets/fonts/WOFF2/OTF/SourceCodePro-Bold.otf.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketrebilcock/js-gpiozero/8d02c3b65604cdd34a0f5ce7c8f905647237dc21/docs/assets/fonts/WOFF2/OTF/SourceCodePro-Bold.otf.woff2 -------------------------------------------------------------------------------- /docs/assets/fonts/WOFF2/OTF/SourceCodePro-Regular.otf.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketrebilcock/js-gpiozero/8d02c3b65604cdd34a0f5ce7c8f905647237dc21/docs/assets/fonts/WOFF2/OTF/SourceCodePro-Regular.otf.woff2 -------------------------------------------------------------------------------- /docs/assets/fonts/WOFF2/TTF/SourceCodePro-Bold.ttf.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketrebilcock/js-gpiozero/8d02c3b65604cdd34a0f5ce7c8f905647237dc21/docs/assets/fonts/WOFF2/TTF/SourceCodePro-Bold.ttf.woff2 -------------------------------------------------------------------------------- /docs/assets/fonts/WOFF2/TTF/SourceCodePro-Regular.ttf.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketrebilcock/js-gpiozero/8d02c3b65604cdd34a0f5ce7c8f905647237dc21/docs/assets/fonts/WOFF2/TTF/SourceCodePro-Regular.ttf.woff2 -------------------------------------------------------------------------------- /docs/assets/fonts/source-code-pro.css: -------------------------------------------------------------------------------- 1 | @font-face{ 2 | font-family: 'Source Code Pro'; 3 | font-weight: 400; 4 | font-style: normal; 5 | font-stretch: normal; 6 | src: url('EOT/SourceCodePro-Regular.eot') format('embedded-opentype'), 7 | url('WOFF2/TTF/SourceCodePro-Regular.ttf.woff2') format('woff2'), 8 | url('WOFF/OTF/SourceCodePro-Regular.otf.woff') format('woff'), 9 | url('OTF/SourceCodePro-Regular.otf') format('opentype'), 10 | url('TTF/SourceCodePro-Regular.ttf') format('truetype'); 11 | } 12 | 13 | @font-face{ 14 | font-family: 'Source Code Pro'; 15 | font-weight: 700; 16 | font-style: normal; 17 | font-stretch: normal; 18 | src: url('EOT/SourceCodePro-Bold.eot') format('embedded-opentype'), 19 | url('WOFF2/TTF/SourceCodePro-Bold.ttf.woff2') format('woff2'), 20 | url('WOFF/OTF/SourceCodePro-Bold.otf.woff') format('woff'), 21 | url('OTF/SourceCodePro-Bold.otf') format('opentype'), 22 | url('TTF/SourceCodePro-Bold.ttf') format('truetype'); 23 | } 24 | -------------------------------------------------------------------------------- /docs/assets/github.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | github.com style (c) Vasily Polovnyov 4 | 5 | */ 6 | 7 | .hljs { 8 | display: block; 9 | overflow-x: auto; 10 | padding: 0.5em; 11 | color: #333; 12 | background: #f8f8f8; 13 | -webkit-text-size-adjust: none; 14 | } 15 | 16 | .hljs-comment, 17 | .diff .hljs-header, 18 | .hljs-javadoc { 19 | color: #998; 20 | font-style: italic; 21 | } 22 | 23 | .hljs-keyword, 24 | .css .rule .hljs-keyword, 25 | .hljs-winutils, 26 | .nginx .hljs-title, 27 | .hljs-subst, 28 | .hljs-request, 29 | .hljs-status { 30 | color: #1184CE; 31 | } 32 | 33 | .hljs-number, 34 | .hljs-hexcolor, 35 | .ruby .hljs-constant { 36 | color: #ed225d; 37 | } 38 | 39 | .hljs-string, 40 | .hljs-tag .hljs-value, 41 | .hljs-phpdoc, 42 | .hljs-dartdoc, 43 | .tex .hljs-formula { 44 | color: #ed225d; 45 | } 46 | 47 | .hljs-title, 48 | .hljs-id, 49 | .scss .hljs-preprocessor { 50 | color: #900; 51 | font-weight: bold; 52 | } 53 | 54 | .hljs-list .hljs-keyword, 55 | .hljs-subst { 56 | font-weight: normal; 57 | } 58 | 59 | .hljs-class .hljs-title, 60 | .hljs-type, 61 | .vhdl .hljs-literal, 62 | .tex .hljs-command { 63 | color: #458; 64 | font-weight: bold; 65 | } 66 | 67 | .hljs-tag, 68 | .hljs-tag .hljs-title, 69 | .hljs-rules .hljs-property, 70 | .django .hljs-tag .hljs-keyword { 71 | color: #000080; 72 | font-weight: normal; 73 | } 74 | 75 | .hljs-attribute, 76 | .hljs-variable, 77 | .lisp .hljs-body { 78 | color: #008080; 79 | } 80 | 81 | .hljs-regexp { 82 | color: #009926; 83 | } 84 | 85 | .hljs-symbol, 86 | .ruby .hljs-symbol .hljs-string, 87 | .lisp .hljs-keyword, 88 | .clojure .hljs-keyword, 89 | .scheme .hljs-keyword, 90 | .tex .hljs-special, 91 | .hljs-prompt { 92 | color: #990073; 93 | } 94 | 95 | .hljs-built_in { 96 | color: #0086b3; 97 | } 98 | 99 | .hljs-preprocessor, 100 | .hljs-pragma, 101 | .hljs-pi, 102 | .hljs-doctype, 103 | .hljs-shebang, 104 | .hljs-cdata { 105 | color: #999; 106 | font-weight: bold; 107 | } 108 | 109 | .hljs-deletion { 110 | background: #fdd; 111 | } 112 | 113 | .hljs-addition { 114 | background: #dfd; 115 | } 116 | 117 | .diff .hljs-change { 118 | background: #0086b3; 119 | } 120 | 121 | .hljs-chunk { 122 | color: #aaa; 123 | } 124 | -------------------------------------------------------------------------------- /docs/assets/site.js: -------------------------------------------------------------------------------- 1 | /* global anchors */ 2 | 3 | // add anchor links to headers 4 | anchors.options.placement = 'left'; 5 | anchors.add('h3'); 6 | 7 | // Filter UI 8 | var tocElements = document.getElementById('toc') 9 | .getElementsByTagName('li'); 10 | 11 | document.getElementById('filter-input') 12 | .addEventListener('keyup', function (e) { 13 | 14 | var i, element, children; 15 | 16 | // enter key 17 | if (e.keyCode === 13) { 18 | // go to the first displayed item in the toc 19 | for (i = 0; i < tocElements.length; i++) { 20 | element = tocElements[i]; 21 | if (!element.classList.contains('display-none')) { 22 | location.replace(element.firstChild.href); 23 | return e.preventDefault(); 24 | } 25 | } 26 | } 27 | 28 | var match = function () { 29 | return true; 30 | }; 31 | 32 | var value = this.value.toLowerCase(); 33 | 34 | if (!value.match(/^\s*$/)) { 35 | match = function (element) { 36 | return element.firstChild.innerHTML.toLowerCase().indexOf(value) !== -1; 37 | }; 38 | } 39 | 40 | for (i = 0; i < tocElements.length; i++) { 41 | element = tocElements[i]; 42 | children = Array.from(element.getElementsByTagName('li')); 43 | if (match(element) || children.some(match)) { 44 | element.classList.remove('display-none'); 45 | } else { 46 | element.classList.add('display-none'); 47 | } 48 | } 49 | }); 50 | 51 | var toggles = document.getElementsByClassName('toggle-step-sibling'); 52 | for (var i = 0; i < toggles.length; i++) { 53 | toggles[i].addEventListener('click', toggleStepSibling); 54 | } 55 | 56 | function toggleStepSibling() { 57 | var stepSibling = this.parentNode.parentNode.parentNode.getElementsByClassName('toggle-target')[0]; 58 | var klass = 'display-none'; 59 | if (stepSibling.classList.contains(klass)) { 60 | stepSibling.classList.remove(klass); 61 | stepSibling.innerHTML = '▾'; 62 | } else { 63 | stepSibling.classList.add(klass); 64 | stepSibling.innerHTML = '▸'; 65 | } 66 | } 67 | 68 | var items = document.getElementsByClassName('toggle-sibling'); 69 | for (var j = 0; j < items.length; j++) { 70 | items[j].addEventListener('click', toggleSibling); 71 | } 72 | 73 | function toggleSibling() { 74 | var stepSibling = this.parentNode.getElementsByClassName('toggle-target')[0]; 75 | var icon = this.getElementsByClassName('icon')[0]; 76 | var klass = 'display-none'; 77 | if (stepSibling.classList.contains(klass)) { 78 | stepSibling.classList.remove(klass); 79 | icon.innerHTML = '▾'; 80 | } else { 81 | stepSibling.classList.add(klass); 82 | icon.innerHTML = '▸'; 83 | } 84 | } 85 | 86 | function showHashTarget(targetId) { 87 | var hashTarget = document.getElementById(targetId); 88 | // new target is hidden 89 | if (hashTarget && hashTarget.offsetHeight === 0 && 90 | hashTarget.parentNode.parentNode.classList.contains('display-none')) { 91 | hashTarget.parentNode.parentNode.classList.remove('display-none'); 92 | } 93 | } 94 | 95 | window.addEventListener('hashchange', function() { 96 | showHashTarget(location.hash.substring(1)); 97 | }); 98 | 99 | showHashTarget(location.hash.substring(1)); 100 | 101 | var toclinks = document.getElementsByClassName('pre-open'); 102 | for (var k = 0; k < toclinks.length; k++) { 103 | toclinks[k].addEventListener('mousedown', preOpen, false); 104 | } 105 | 106 | function preOpen() { 107 | showHashTarget(this.hash.substring(1)); 108 | } 109 | -------------------------------------------------------------------------------- /docs/assets/style.css: -------------------------------------------------------------------------------- 1 | .documentation { 2 | font-family: Helvetica, sans-serif; 3 | color: #666; 4 | line-height: 1.5; 5 | background: #f5f5f5; 6 | } 7 | 8 | .black { 9 | color: #666; 10 | } 11 | 12 | .bg-white { 13 | background-color: #fff; 14 | } 15 | 16 | h4 { 17 | margin: 20px 0 10px 0; 18 | } 19 | 20 | .documentation h3 { 21 | color: #000; 22 | } 23 | 24 | .border-bottom { 25 | border-color: #ddd; 26 | } 27 | 28 | a { 29 | color: #1184CE; 30 | text-decoration: none; 31 | } 32 | 33 | .documentation a[href]:hover { 34 | text-decoration: underline; 35 | } 36 | 37 | a:hover { 38 | cursor: pointer; 39 | } 40 | 41 | .py1-ul li { 42 | padding: 5px 0; 43 | } 44 | 45 | .max-height-100 { 46 | max-height: 100%; 47 | } 48 | 49 | section:target h3 { 50 | font-weight:700; 51 | } 52 | 53 | .documentation td, 54 | .documentation th { 55 | padding: .25rem .25rem; 56 | } 57 | 58 | h1:hover .anchorjs-link, 59 | h2:hover .anchorjs-link, 60 | h3:hover .anchorjs-link, 61 | h4:hover .anchorjs-link { 62 | opacity: 1; 63 | } 64 | 65 | .fix-3 { 66 | width: 25%; 67 | max-width: 244px; 68 | } 69 | 70 | .fix-3 { 71 | width: 25%; 72 | max-width: 244px; 73 | } 74 | 75 | @media (min-width: 52em) { 76 | .fix-margin-3 { 77 | margin-left: 25%; 78 | } 79 | } 80 | 81 | .pre, pre, code, .code { 82 | font-family: Source Code Pro,Menlo,Consolas,Liberation Mono,monospace; 83 | font-size: 14px; 84 | } 85 | 86 | .fill-light { 87 | background: #F9F9F9; 88 | } 89 | 90 | .width2 { 91 | width: 1rem; 92 | } 93 | 94 | .input { 95 | font-family: inherit; 96 | display: block; 97 | width: 100%; 98 | height: 2rem; 99 | padding: .5rem; 100 | margin-bottom: 1rem; 101 | border: 1px solid #ccc; 102 | font-size: .875rem; 103 | border-radius: 3px; 104 | box-sizing: border-box; 105 | } 106 | 107 | table { 108 | border-collapse: collapse; 109 | } 110 | 111 | .prose table th, 112 | .prose table td { 113 | text-align: left; 114 | padding:8px; 115 | border:1px solid #ddd; 116 | } 117 | 118 | .prose table th:nth-child(1) { border-right: none; } 119 | .prose table th:nth-child(2) { border-left: none; } 120 | 121 | .prose table { 122 | border:1px solid #ddd; 123 | } 124 | 125 | .prose-big { 126 | font-size: 18px; 127 | line-height: 30px; 128 | } 129 | 130 | .quiet { 131 | opacity: 0.7; 132 | } 133 | 134 | .minishadow { 135 | box-shadow: 2px 2px 10px #f3f3f3; 136 | } 137 | -------------------------------------------------------------------------------- /docs/fonts/OpenSans-Bold-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketrebilcock/js-gpiozero/8d02c3b65604cdd34a0f5ce7c8f905647237dc21/docs/fonts/OpenSans-Bold-webfont.eot -------------------------------------------------------------------------------- /docs/fonts/OpenSans-Bold-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketrebilcock/js-gpiozero/8d02c3b65604cdd34a0f5ce7c8f905647237dc21/docs/fonts/OpenSans-Bold-webfont.woff -------------------------------------------------------------------------------- /docs/fonts/OpenSans-BoldItalic-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketrebilcock/js-gpiozero/8d02c3b65604cdd34a0f5ce7c8f905647237dc21/docs/fonts/OpenSans-BoldItalic-webfont.eot -------------------------------------------------------------------------------- /docs/fonts/OpenSans-BoldItalic-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketrebilcock/js-gpiozero/8d02c3b65604cdd34a0f5ce7c8f905647237dc21/docs/fonts/OpenSans-BoldItalic-webfont.woff -------------------------------------------------------------------------------- /docs/fonts/OpenSans-Italic-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketrebilcock/js-gpiozero/8d02c3b65604cdd34a0f5ce7c8f905647237dc21/docs/fonts/OpenSans-Italic-webfont.eot -------------------------------------------------------------------------------- /docs/fonts/OpenSans-Italic-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketrebilcock/js-gpiozero/8d02c3b65604cdd34a0f5ce7c8f905647237dc21/docs/fonts/OpenSans-Italic-webfont.woff -------------------------------------------------------------------------------- /docs/fonts/OpenSans-Light-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketrebilcock/js-gpiozero/8d02c3b65604cdd34a0f5ce7c8f905647237dc21/docs/fonts/OpenSans-Light-webfont.eot -------------------------------------------------------------------------------- /docs/fonts/OpenSans-Light-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketrebilcock/js-gpiozero/8d02c3b65604cdd34a0f5ce7c8f905647237dc21/docs/fonts/OpenSans-Light-webfont.woff -------------------------------------------------------------------------------- /docs/fonts/OpenSans-LightItalic-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketrebilcock/js-gpiozero/8d02c3b65604cdd34a0f5ce7c8f905647237dc21/docs/fonts/OpenSans-LightItalic-webfont.eot -------------------------------------------------------------------------------- /docs/fonts/OpenSans-LightItalic-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketrebilcock/js-gpiozero/8d02c3b65604cdd34a0f5ce7c8f905647237dc21/docs/fonts/OpenSans-LightItalic-webfont.woff -------------------------------------------------------------------------------- /docs/fonts/OpenSans-Regular-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketrebilcock/js-gpiozero/8d02c3b65604cdd34a0f5ce7c8f905647237dc21/docs/fonts/OpenSans-Regular-webfont.eot -------------------------------------------------------------------------------- /docs/fonts/OpenSans-Regular-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketrebilcock/js-gpiozero/8d02c3b65604cdd34a0f5ce7c8f905647237dc21/docs/fonts/OpenSans-Regular-webfont.woff -------------------------------------------------------------------------------- /docs/scripts/linenumber.js: -------------------------------------------------------------------------------- 1 | /*global document */ 2 | (function() { 3 | var source = document.getElementsByClassName('prettyprint source linenums'); 4 | var i = 0; 5 | var lineNumber = 0; 6 | var lineId; 7 | var lines; 8 | var totalLines; 9 | var anchorHash; 10 | 11 | if (source && source[0]) { 12 | anchorHash = document.location.hash.substring(1); 13 | lines = source[0].getElementsByTagName('li'); 14 | totalLines = lines.length; 15 | 16 | for (; i < totalLines; i++) { 17 | lineNumber++; 18 | lineId = 'line' + lineNumber; 19 | lines[i].id = lineId; 20 | if (lineId === anchorHash) { 21 | lines[i].className += ' selected'; 22 | } 23 | } 24 | } 25 | })(); 26 | -------------------------------------------------------------------------------- /docs/scripts/prettify/lang-css.js: -------------------------------------------------------------------------------- 1 | PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n "]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com", 2 | /^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]); 3 | -------------------------------------------------------------------------------- /docs/styles/jsdoc-default.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Open Sans'; 3 | font-weight: normal; 4 | font-style: normal; 5 | src: url('../fonts/OpenSans-Regular-webfont.eot'); 6 | src: 7 | local('Open Sans'), 8 | local('OpenSans'), 9 | url('../fonts/OpenSans-Regular-webfont.eot?#iefix') format('embedded-opentype'), 10 | url('../fonts/OpenSans-Regular-webfont.woff') format('woff'), 11 | url('../fonts/OpenSans-Regular-webfont.svg#open_sansregular') format('svg'); 12 | } 13 | 14 | @font-face { 15 | font-family: 'Open Sans Light'; 16 | font-weight: normal; 17 | font-style: normal; 18 | src: url('../fonts/OpenSans-Light-webfont.eot'); 19 | src: 20 | local('Open Sans Light'), 21 | local('OpenSans Light'), 22 | url('../fonts/OpenSans-Light-webfont.eot?#iefix') format('embedded-opentype'), 23 | url('../fonts/OpenSans-Light-webfont.woff') format('woff'), 24 | url('../fonts/OpenSans-Light-webfont.svg#open_sanslight') format('svg'); 25 | } 26 | 27 | html 28 | { 29 | overflow: auto; 30 | background-color: #fff; 31 | font-size: 14px; 32 | } 33 | 34 | body 35 | { 36 | font-family: 'Open Sans', sans-serif; 37 | line-height: 1.5; 38 | color: #4d4e53; 39 | background-color: white; 40 | } 41 | 42 | a, a:visited, a:active { 43 | color: #0095dd; 44 | text-decoration: none; 45 | } 46 | 47 | a:hover { 48 | text-decoration: underline; 49 | } 50 | 51 | header 52 | { 53 | display: block; 54 | padding: 0px 4px; 55 | } 56 | 57 | tt, code, kbd, samp { 58 | font-family: Consolas, Monaco, 'Andale Mono', monospace; 59 | } 60 | 61 | .class-description { 62 | font-size: 130%; 63 | line-height: 140%; 64 | margin-bottom: 1em; 65 | margin-top: 1em; 66 | } 67 | 68 | .class-description:empty { 69 | margin: 0; 70 | } 71 | 72 | #main { 73 | float: left; 74 | width: 70%; 75 | } 76 | 77 | article dl { 78 | margin-bottom: 40px; 79 | } 80 | 81 | section 82 | { 83 | display: block; 84 | background-color: #fff; 85 | padding: 12px 24px; 86 | border-bottom: 1px solid #ccc; 87 | margin-right: 30px; 88 | } 89 | 90 | .variation { 91 | display: none; 92 | } 93 | 94 | .signature-attributes { 95 | font-size: 60%; 96 | color: #aaa; 97 | font-style: italic; 98 | font-weight: lighter; 99 | } 100 | 101 | nav 102 | { 103 | display: block; 104 | float: right; 105 | margin-top: 28px; 106 | width: 30%; 107 | box-sizing: border-box; 108 | border-left: 1px solid #ccc; 109 | padding-left: 16px; 110 | } 111 | 112 | nav ul { 113 | font-family: 'Lucida Grande', 'Lucida Sans Unicode', arial, sans-serif; 114 | font-size: 100%; 115 | line-height: 17px; 116 | padding: 0; 117 | margin: 0; 118 | list-style-type: none; 119 | } 120 | 121 | nav ul a, nav ul a:visited, nav ul a:active { 122 | font-family: Consolas, Monaco, 'Andale Mono', monospace; 123 | line-height: 18px; 124 | color: #4D4E53; 125 | } 126 | 127 | nav h3 { 128 | margin-top: 12px; 129 | } 130 | 131 | nav li { 132 | margin-top: 6px; 133 | } 134 | 135 | footer { 136 | display: block; 137 | padding: 6px; 138 | margin-top: 12px; 139 | font-style: italic; 140 | font-size: 90%; 141 | } 142 | 143 | h1, h2, h3, h4 { 144 | font-weight: 200; 145 | margin: 0; 146 | } 147 | 148 | h1 149 | { 150 | font-family: 'Open Sans Light', sans-serif; 151 | font-size: 48px; 152 | letter-spacing: -2px; 153 | margin: 12px 24px 20px; 154 | } 155 | 156 | h2, h3.subsection-title 157 | { 158 | font-size: 30px; 159 | font-weight: 700; 160 | letter-spacing: -1px; 161 | margin-bottom: 12px; 162 | } 163 | 164 | h3 165 | { 166 | font-size: 24px; 167 | letter-spacing: -0.5px; 168 | margin-bottom: 12px; 169 | } 170 | 171 | h4 172 | { 173 | font-size: 18px; 174 | letter-spacing: -0.33px; 175 | margin-bottom: 12px; 176 | color: #4d4e53; 177 | } 178 | 179 | h5, .container-overview .subsection-title 180 | { 181 | font-size: 120%; 182 | font-weight: bold; 183 | letter-spacing: -0.01em; 184 | margin: 8px 0 3px 0; 185 | } 186 | 187 | h6 188 | { 189 | font-size: 100%; 190 | letter-spacing: -0.01em; 191 | margin: 6px 0 3px 0; 192 | font-style: italic; 193 | } 194 | 195 | table 196 | { 197 | border-spacing: 0; 198 | border: 0; 199 | border-collapse: collapse; 200 | } 201 | 202 | td, th 203 | { 204 | border: 1px solid #ddd; 205 | margin: 0px; 206 | text-align: left; 207 | vertical-align: top; 208 | padding: 4px 6px; 209 | display: table-cell; 210 | } 211 | 212 | thead tr 213 | { 214 | background-color: #ddd; 215 | font-weight: bold; 216 | } 217 | 218 | th { border-right: 1px solid #aaa; } 219 | tr > th:last-child { border-right: 1px solid #ddd; } 220 | 221 | .ancestors { color: #999; } 222 | .ancestors a 223 | { 224 | color: #999 !important; 225 | text-decoration: none; 226 | } 227 | 228 | .clear 229 | { 230 | clear: both; 231 | } 232 | 233 | .important 234 | { 235 | font-weight: bold; 236 | color: #950B02; 237 | } 238 | 239 | .yes-def { 240 | text-indent: -1000px; 241 | } 242 | 243 | .type-signature { 244 | color: #aaa; 245 | } 246 | 247 | .name, .signature { 248 | font-family: Consolas, Monaco, 'Andale Mono', monospace; 249 | } 250 | 251 | .details { margin-top: 14px; border-left: 2px solid #DDD; } 252 | .details dt { width: 120px; float: left; padding-left: 10px; padding-top: 6px; } 253 | .details dd { margin-left: 70px; } 254 | .details ul { margin: 0; } 255 | .details ul { list-style-type: none; } 256 | .details li { margin-left: 30px; padding-top: 6px; } 257 | .details pre.prettyprint { margin: 0 } 258 | .details .object-value { padding-top: 0; } 259 | 260 | .description { 261 | margin-bottom: 1em; 262 | margin-top: 1em; 263 | } 264 | 265 | .code-caption 266 | { 267 | font-style: italic; 268 | font-size: 107%; 269 | margin: 0; 270 | } 271 | 272 | .prettyprint 273 | { 274 | border: 1px solid #ddd; 275 | width: 80%; 276 | overflow: auto; 277 | } 278 | 279 | .prettyprint.source { 280 | width: inherit; 281 | } 282 | 283 | .prettyprint code 284 | { 285 | font-size: 100%; 286 | line-height: 18px; 287 | display: block; 288 | padding: 4px 12px; 289 | margin: 0; 290 | background-color: #fff; 291 | color: #4D4E53; 292 | } 293 | 294 | .prettyprint code span.line 295 | { 296 | display: inline-block; 297 | } 298 | 299 | .prettyprint.linenums 300 | { 301 | padding-left: 70px; 302 | -webkit-user-select: none; 303 | -moz-user-select: none; 304 | -ms-user-select: none; 305 | user-select: none; 306 | } 307 | 308 | .prettyprint.linenums ol 309 | { 310 | padding-left: 0; 311 | } 312 | 313 | .prettyprint.linenums li 314 | { 315 | border-left: 3px #ddd solid; 316 | } 317 | 318 | .prettyprint.linenums li.selected, 319 | .prettyprint.linenums li.selected * 320 | { 321 | background-color: lightyellow; 322 | } 323 | 324 | .prettyprint.linenums li * 325 | { 326 | -webkit-user-select: text; 327 | -moz-user-select: text; 328 | -ms-user-select: text; 329 | user-select: text; 330 | } 331 | 332 | .params .name, .props .name, .name code { 333 | color: #4D4E53; 334 | font-family: Consolas, Monaco, 'Andale Mono', monospace; 335 | font-size: 100%; 336 | } 337 | 338 | .params td.description > p:first-child, 339 | .props td.description > p:first-child 340 | { 341 | margin-top: 0; 342 | padding-top: 0; 343 | } 344 | 345 | .params td.description > p:last-child, 346 | .props td.description > p:last-child 347 | { 348 | margin-bottom: 0; 349 | padding-bottom: 0; 350 | } 351 | 352 | .disabled { 353 | color: #454545; 354 | } 355 | -------------------------------------------------------------------------------- /docs/styles/prettify-jsdoc.css: -------------------------------------------------------------------------------- 1 | /* JSDoc prettify.js theme */ 2 | 3 | /* plain text */ 4 | .pln { 5 | color: #000000; 6 | font-weight: normal; 7 | font-style: normal; 8 | } 9 | 10 | /* string content */ 11 | .str { 12 | color: #006400; 13 | font-weight: normal; 14 | font-style: normal; 15 | } 16 | 17 | /* a keyword */ 18 | .kwd { 19 | color: #000000; 20 | font-weight: bold; 21 | font-style: normal; 22 | } 23 | 24 | /* a comment */ 25 | .com { 26 | font-weight: normal; 27 | font-style: italic; 28 | } 29 | 30 | /* a type name */ 31 | .typ { 32 | color: #000000; 33 | font-weight: normal; 34 | font-style: normal; 35 | } 36 | 37 | /* a literal value */ 38 | .lit { 39 | color: #006400; 40 | font-weight: normal; 41 | font-style: normal; 42 | } 43 | 44 | /* punctuation */ 45 | .pun { 46 | color: #000000; 47 | font-weight: bold; 48 | font-style: normal; 49 | } 50 | 51 | /* lisp open bracket */ 52 | .opn { 53 | color: #000000; 54 | font-weight: bold; 55 | font-style: normal; 56 | } 57 | 58 | /* lisp close bracket */ 59 | .clo { 60 | color: #000000; 61 | font-weight: bold; 62 | font-style: normal; 63 | } 64 | 65 | /* a markup tag name */ 66 | .tag { 67 | color: #006400; 68 | font-weight: normal; 69 | font-style: normal; 70 | } 71 | 72 | /* a markup attribute name */ 73 | .atn { 74 | color: #006400; 75 | font-weight: normal; 76 | font-style: normal; 77 | } 78 | 79 | /* a markup attribute value */ 80 | .atv { 81 | color: #006400; 82 | font-weight: normal; 83 | font-style: normal; 84 | } 85 | 86 | /* a declaration */ 87 | .dec { 88 | color: #000000; 89 | font-weight: bold; 90 | font-style: normal; 91 | } 92 | 93 | /* a variable name */ 94 | .var { 95 | color: #000000; 96 | font-weight: normal; 97 | font-style: normal; 98 | } 99 | 100 | /* a function name */ 101 | .fun { 102 | color: #000000; 103 | font-weight: bold; 104 | font-style: normal; 105 | } 106 | 107 | /* Specify class=linenums on a pre to get line numbering */ 108 | ol.linenums { 109 | margin-top: 0; 110 | margin-bottom: 0; 111 | } 112 | -------------------------------------------------------------------------------- /docs/styles/prettify-tomorrow.css: -------------------------------------------------------------------------------- 1 | /* Tomorrow Theme */ 2 | /* Original theme - https://github.com/chriskempson/tomorrow-theme */ 3 | /* Pretty printing styles. Used with prettify.js. */ 4 | /* SPAN elements with the classes below are added by prettyprint. */ 5 | /* plain text */ 6 | .pln { 7 | color: #4d4d4c; } 8 | 9 | @media screen { 10 | /* string content */ 11 | .str { 12 | color: #718c00; } 13 | 14 | /* a keyword */ 15 | .kwd { 16 | color: #8959a8; } 17 | 18 | /* a comment */ 19 | .com { 20 | color: #8e908c; } 21 | 22 | /* a type name */ 23 | .typ { 24 | color: #4271ae; } 25 | 26 | /* a literal value */ 27 | .lit { 28 | color: #f5871f; } 29 | 30 | /* punctuation */ 31 | .pun { 32 | color: #4d4d4c; } 33 | 34 | /* lisp open bracket */ 35 | .opn { 36 | color: #4d4d4c; } 37 | 38 | /* lisp close bracket */ 39 | .clo { 40 | color: #4d4d4c; } 41 | 42 | /* a markup tag name */ 43 | .tag { 44 | color: #c82829; } 45 | 46 | /* a markup attribute name */ 47 | .atn { 48 | color: #f5871f; } 49 | 50 | /* a markup attribute value */ 51 | .atv { 52 | color: #3e999f; } 53 | 54 | /* a declaration */ 55 | .dec { 56 | color: #f5871f; } 57 | 58 | /* a variable name */ 59 | .var { 60 | color: #c82829; } 61 | 62 | /* a function name */ 63 | .fun { 64 | color: #4271ae; } } 65 | /* Use higher contrast and text-weight for printable form. */ 66 | @media print, projection { 67 | .str { 68 | color: #060; } 69 | 70 | .kwd { 71 | color: #006; 72 | font-weight: bold; } 73 | 74 | .com { 75 | color: #600; 76 | font-style: italic; } 77 | 78 | .typ { 79 | color: #404; 80 | font-weight: bold; } 81 | 82 | .lit { 83 | color: #044; } 84 | 85 | .pun, .opn, .clo { 86 | color: #440; } 87 | 88 | .tag { 89 | color: #006; 90 | font-weight: bold; } 91 | 92 | .atn { 93 | color: #404; } 94 | 95 | .atv { 96 | color: #060; } } 97 | /* Style */ 98 | /* 99 | pre.prettyprint { 100 | background: white; 101 | font-family: Consolas, Monaco, 'Andale Mono', monospace; 102 | font-size: 12px; 103 | line-height: 1.5; 104 | border: 1px solid #ccc; 105 | padding: 10px; } 106 | */ 107 | 108 | /* Specify class=linenums on a pre to get line numbering */ 109 | ol.linenums { 110 | margin-top: 0; 111 | margin-bottom: 0; } 112 | 113 | /* IE indents via margin-left */ 114 | li.L0, 115 | li.L1, 116 | li.L2, 117 | li.L3, 118 | li.L4, 119 | li.L5, 120 | li.L6, 121 | li.L7, 122 | li.L8, 123 | li.L9 { 124 | /* */ } 125 | 126 | /* Alternate shading for lines */ 127 | li.L1, 128 | li.L3, 129 | li.L5, 130 | li.L7, 131 | li.L9 { 132 | /* */ } 133 | -------------------------------------------------------------------------------- /docs/styles/prettify.css: -------------------------------------------------------------------------------- 1 | .pln { 2 | color: #ddd; 3 | } 4 | 5 | /* string content */ 6 | .str { 7 | color: #61ce3c; 8 | } 9 | 10 | /* a keyword */ 11 | .kwd { 12 | color: #fbde2d; 13 | } 14 | 15 | /* a comment */ 16 | .com { 17 | color: #aeaeae; 18 | } 19 | 20 | /* a type name */ 21 | .typ { 22 | color: #8da6ce; 23 | } 24 | 25 | /* a literal value */ 26 | .lit { 27 | color: #fbde2d; 28 | } 29 | 30 | /* punctuation */ 31 | .pun { 32 | color: #ddd; 33 | } 34 | 35 | /* lisp open bracket */ 36 | .opn { 37 | color: #000000; 38 | } 39 | 40 | /* lisp close bracket */ 41 | .clo { 42 | color: #000000; 43 | } 44 | 45 | /* a markup tag name */ 46 | .tag { 47 | color: #8da6ce; 48 | } 49 | 50 | /* a markup attribute name */ 51 | .atn { 52 | color: #fbde2d; 53 | } 54 | 55 | /* a markup attribute value */ 56 | .atv { 57 | color: #ddd; 58 | } 59 | 60 | /* a declaration */ 61 | .dec { 62 | color: #EF5050; 63 | } 64 | 65 | /* a variable name */ 66 | .var { 67 | color: #c82829; 68 | } 69 | 70 | /* a function name */ 71 | .fun { 72 | color: #4271ae; 73 | } 74 | 75 | /* Specify class=linenums on a pre to get line numbering */ 76 | ol.linenums { 77 | margin-top: 0; 78 | margin-bottom: 0; 79 | } 80 | -------------------------------------------------------------------------------- /gpiozero/Mixins/EventsMixin.js: -------------------------------------------------------------------------------- 1 | 2 | function EventsMixin () { 3 | this._active_event = false; 4 | this._inactive_event = false; 5 | this.when_activated = null; 6 | this.when_deactivated = null; 7 | this._last_state = null; 8 | this._last_changed = (new Date()).getTime(); 9 | } 10 | 11 | exports.EventsMixin = EventsMixin; 12 | 13 | EventsMixin.prototype._fire_events = function() { 14 | const old_state = this._last_state; 15 | const new_state = this._last_state = this.is_active(); 16 | if (old_state === null) { 17 | // Initial "indeterminate" state; set events but don't fire 18 | // callbacks as there's not necessarily an edge 19 | if (new_state !== false) { 20 | this._active_event = true; 21 | } else { 22 | this._inactive_event = true; 23 | } 24 | } else if (old_state !== new_state) { 25 | this._last_changed = (new Date()).getTime(); 26 | if (new_state !== false) { 27 | this._inactive_event = false; 28 | this._active_event = true; 29 | this._fire_activated(); 30 | } else { 31 | this._active_event = false; 32 | this._inactive_event = true; 33 | this._fire_deactivated(); 34 | } 35 | } 36 | }; 37 | 38 | /** 39 | * These methods are largely here to be overridden by descendents. 40 | * 41 | * @private 42 | */ 43 | EventsMixin.prototype._fire_activated = function () { 44 | if (this.when_activated !== null) { 45 | this.when_activated(); 46 | } 47 | }; 48 | 49 | /** 50 | * These methods are largely here to be overridden by descendents. 51 | * 52 | * @private 53 | */ 54 | EventsMixin.prototype._fire_deactivated = function () { 55 | if (this.when_deactivated !== null) { 56 | this.when_deactivated(); 57 | } 58 | }; 59 | 60 | /* 61 | def wait_for_active(self, timeout=None): 62 | """ 63 | Pause the script until the device is activated, or the timeout is 64 | reached. 65 | 66 | :param float timeout: 67 | Number of seconds to wait before proceeding. If this is ``None`` 68 | (the default), then wait indefinitely until the device is active. 69 | """ 70 | return self._active_event.wait(timeout) 71 | 72 | def wait_for_inactive(self, timeout=None): 73 | """ 74 | Pause the script until the device is deactivated, or the timeout is 75 | reached. 76 | 77 | :param float timeout: 78 | Number of seconds to wait before proceeding. If this is ``None`` 79 | (the default), then wait indefinitely until the device is inactive. 80 | """ 81 | return self._inactive_event.wait(timeout) 82 | 83 | @property 84 | def when_activated(self): 85 | """ 86 | The function to run when the device changes state from inactive to 87 | active. 88 | 89 | This can be set to a function which accepts no (mandatory) parameters, 90 | or a Python function which accepts a single mandatory parameter (with 91 | as many optional parameters as you like). If the function accepts a 92 | single mandatory parameter, the device that activated will be passed 93 | as that parameter. 94 | 95 | Set this property to ``None`` (the default) to disable the event. 96 | """ 97 | return self._when_activated 98 | 99 | @when_activated.setter 100 | def when_activated(self, value): 101 | self._when_activated = self._wrap_callback(value) 102 | 103 | @property 104 | def when_deactivated(self): 105 | """ 106 | The function to run when the device changes state from active to 107 | inactive. 108 | 109 | This can be set to a function which accepts no (mandatory) parameters, 110 | or a Python function which accepts a single mandatory parameter (with 111 | as many optional parameters as you like). If the function accepts a 112 | single mandatory parameter, the device that deactivated will be 113 | passed as that parameter. 114 | 115 | Set this property to ``None`` (the default) to disable the event. 116 | """ 117 | return self._when_deactivated 118 | 119 | @when_deactivated.setter 120 | def when_deactivated(self, value): 121 | self._when_deactivated = self._wrap_callback(value) 122 | 123 | @property 124 | def active_time(self): 125 | """ 126 | The length of time (in seconds) that the device has been active for. 127 | When the device is inactive, this is ``None``. 128 | """ 129 | if self._active_event.is_set(): 130 | return time() - self._last_changed 131 | else: 132 | return None 133 | 134 | @property 135 | def inactive_time(self): 136 | """ 137 | The length of time (in seconds) that the device has been inactive for. 138 | When the device is active, this is ``None``. 139 | """ 140 | if self._inactive_event.is_set(): 141 | return time() - self._last_changed 142 | else: 143 | return None 144 | 145 | def _wrap_callback(self, fn): 146 | if fn is None: 147 | return None 148 | elif not callable(fn): 149 | raise BadEventHandler('value must be None or a callable') 150 | # If fn is wrapped with partial (i.e. partial, partialmethod, or wraps 151 | # has been used to produce it) we need to dig out the "real" function 152 | # that's been wrapped along with all the mandatory positional args 153 | # used in the wrapper so we can test the binding 154 | args = () 155 | wrapped_fn = fn 156 | while isinstance(wrapped_fn, partial): 157 | args = wrapped_fn.args + args 158 | wrapped_fn = wrapped_fn.func 159 | if inspect.isbuiltin(wrapped_fn): 160 | # We can't introspect the prototype of builtins. In this case we 161 | # assume that the builtin has no (mandatory) parameters; this is 162 | # the most reasonable assumption on the basis that pre-existing 163 | # builtins have no knowledge of gpiozero, and the sole parameter 164 | # we would pass is a gpiozero object 165 | return fn 166 | else: 167 | # Try binding ourselves to the argspec of the provided callable. 168 | # If this works, assume the function is capable of accepting no 169 | # parameters 170 | try: 171 | inspect.getcallargs(wrapped_fn, *args) 172 | return fn 173 | except TypeError: 174 | try: 175 | # If the above fails, try binding with a single parameter 176 | # (ourselves). If this works, wrap the specified callback 177 | inspect.getcallargs(wrapped_fn, *(args + (self,))) 178 | @wraps(fn) 179 | def wrapper(): 180 | return fn(self) 181 | return wrapper 182 | except TypeError: 183 | raise BadEventHandler( 184 | 'value must be a callable which accepts up to one ' 185 | 'mandatory parameter') 186 | */ 187 | -------------------------------------------------------------------------------- /gpiozero/boards/LEDBoard.js: -------------------------------------------------------------------------------- 1 | const LEDCollection = require ('./LEDCollection.js').LEDCollection; 2 | const inherit = require ('../tools.js').inherit; 3 | const extend = require ('../tools.js').extend; 4 | const ReadWriteLock = require('rwlock'); 5 | 6 | exports.LEDBoard = LEDBoard; 7 | 8 | /** 9 | * Represents a generic LED board or collection of LEDs. 10 | * The following example turns on all the LEDs on a board containing 5 LEDs attached to GPIO pins 2 through 6. 11 | * 12 | * @example 13 | * const LEDBoard = require('gpiozero').LEDBoard; 14 | * var leds = new LEDBoard([2, 3, 4, 5, 6]); 15 | * leds.on(); 16 | * 17 | * @param {Array} pins - Specify the GPIO pins that the LEDs of the board are attached to. You can designate as many pins as necessary. 18 | * @param {Array} kwpins - Specify an array of arrays that has the Name of the device and the GPIO pins that the LEDs of the board are attached to. 19 | * You can designate as many pins as necessary. 20 | * @param {Object} _options - Set options for the Collection: 21 | * * pwm: Default: false, If true, creates PWMLED instances for each pin, else LED. 22 | * * active_high: Default: true, If true, the on method will set all the associated pins to HIGH. 23 | * If false, the on method will set all pins to LOW (the `off` method always does the opposite). 24 | * * initial_value: If false, all LEDs will be off initially, if true the device will be Switched on initialled. 25 | * @augments LEDCollection 26 | * @class 27 | */ 28 | function LEDBoard(pins, kwpins, _options) { 29 | "use strict"; 30 | const defaults = { 31 | pwm: false, 32 | active_high: true, 33 | initial_value: false, 34 | }; 35 | this.options = extend(defaults, _options); 36 | this._blink_leds = []; 37 | this._blink_lock = new ReadWriteLock(); 38 | LEDCollection.call(this, pins, kwpins, this.options); 39 | } 40 | LEDBoard.prototype = inherit(LEDCollection.prototype); 41 | LEDBoard.prototype.constructor = LEDBoard; 42 | 43 | LEDBoard.prototype.close = function () { 44 | LEDCollection.prototype.close.call(this); 45 | } 46 | 47 | /* 48 | class LEDBoard(LEDCollection): 49 | 50 | def close(self): 51 | self._stop_blink() 52 | super(LEDBoard, self).close() 53 | 54 | def on(self, *args): 55 | self._stop_blink() 56 | if args: 57 | for index in args: 58 | self[index].on() 59 | else: 60 | super(LEDBoard, self).on() 61 | 62 | def off(self, *args): 63 | self._stop_blink() 64 | if args: 65 | for index in args: 66 | self[index].off() 67 | else: 68 | super(LEDBoard, self).off() 69 | 70 | def toggle(self, *args): 71 | self._stop_blink() 72 | if args: 73 | for index in args: 74 | self[index].toggle() 75 | else: 76 | super(LEDBoard, self).toggle() 77 | 78 | def blink( 79 | self, on_time=1, off_time=1, fade_in_time=0, fade_out_time=0, 80 | n=None, background=True): 81 | """ 82 | Make all the LEDs turn on and off repeatedly. 83 | 84 | :param float on_time: 85 | Number of seconds on. Defaults to 1 second. 86 | 87 | :param float off_time: 88 | Number of seconds off. Defaults to 1 second. 89 | 90 | :param float fade_in_time: 91 | Number of seconds to spend fading in. Defaults to 0. Must be 0 if 92 | ``pwm`` was ``False`` when the class was constructed 93 | (:exc:`ValueError` will be raised if not). 94 | 95 | :param float fade_out_time: 96 | Number of seconds to spend fading out. Defaults to 0. Must be 0 if 97 | ``pwm`` was ``False`` when the class was constructed 98 | (:exc:`ValueError` will be raised if not). 99 | 100 | :param int n: 101 | Number of times to blink; ``None`` (the default) means forever. 102 | 103 | :param bool background: 104 | If ``True``, start a background thread to continue blinking and 105 | return immediately. If ``False``, only return when the blink is 106 | finished (warning: the default value of *n* will result in this 107 | method never returning). 108 | """ 109 | for led in self.leds: 110 | if isinstance(led, LED): 111 | if fade_in_time: 112 | raise ValueError('fade_in_time must be 0 with non-PWM LEDs') 113 | if fade_out_time: 114 | raise ValueError('fade_out_time must be 0 with non-PWM LEDs') 115 | self._stop_blink() 116 | self._blink_thread = GPIOThread( 117 | target=self._blink_device, 118 | args=(on_time, off_time, fade_in_time, fade_out_time, n) 119 | ) 120 | self._blink_thread.start() 121 | if not background: 122 | self._blink_thread.join() 123 | self._blink_thread = None 124 | 125 | def _stop_blink(self, led=None): 126 | if led is None: 127 | if self._blink_thread: 128 | self._blink_thread.stop() 129 | self._blink_thread = None 130 | else: 131 | with self._blink_lock: 132 | self._blink_leds.remove(led) 133 | 134 | def pulse(self, fade_in_time=1, fade_out_time=1, n=None, background=True): 135 | """ 136 | Make the device fade in and out repeatedly. 137 | 138 | :param float fade_in_time: 139 | Number of seconds to spend fading in. Defaults to 1. 140 | 141 | :param float fade_out_time: 142 | Number of seconds to spend fading out. Defaults to 1. 143 | 144 | :param int n: 145 | Number of times to blink; ``None`` (the default) means forever. 146 | 147 | :param bool background: 148 | If ``True`` (the default), start a background thread to continue 149 | blinking and return immediately. If ``False``, only return when the 150 | blink is finished (warning: the default value of *n* will result in 151 | this method never returning). 152 | """ 153 | on_time = off_time = 0 154 | self.blink( 155 | on_time, off_time, fade_in_time, fade_out_time, n, background 156 | ) 157 | 158 | def _blink_device(self, on_time, off_time, fade_in_time, fade_out_time, n, fps=25): 159 | sequence = [] 160 | if fade_in_time > 0: 161 | sequence += [ 162 | (i * (1 / fps) / fade_in_time, 1 / fps) 163 | for i in range(int(fps * fade_in_time)) 164 | ] 165 | sequence.append((1, on_time)) 166 | if fade_out_time > 0: 167 | sequence += [ 168 | (1 - (i * (1 / fps) / fade_out_time), 1 / fps) 169 | for i in range(int(fps * fade_out_time)) 170 | ] 171 | sequence.append((0, off_time)) 172 | sequence = ( 173 | cycle(sequence) if n is None else 174 | chain.from_iterable(repeat(sequence, n)) 175 | ) 176 | with self._blink_lock: 177 | self._blink_leds = list(self.leds) 178 | for led in self._blink_leds: 179 | if led._controller not in (None, self): 180 | led._controller._stop_blink(led) 181 | led._controller = self 182 | for value, delay in sequence: 183 | with self._blink_lock: 184 | if not self._blink_leds: 185 | break 186 | for led in self._blink_leds: 187 | led._write(value) 188 | if self._blink_thread.stopping.wait(delay): 189 | break 190 | */ 191 | -------------------------------------------------------------------------------- /gpiozero/boards/LEDCollection.js: -------------------------------------------------------------------------------- 1 | const inherit = require ('../tools.js').inherit; 2 | const extend = require ('../tools.js').extend; 3 | const CompositeOutputDevice = require ('../output_devices/CompositeOutputDevice.js').CompositeOutputDevice; 4 | const PWMLED = require('../output_devices/PWMLED.js').PWMLED; 5 | const LED = require('../output_devices/LED.js').LED; 6 | 7 | exports.LEDCollection = LEDCollection; 8 | 9 | /** 10 | * Abstract base class for @link{LEDBoard} and @link{LEDBarGraph}. 11 | * 12 | * @param {Array} [_pins] - Array of pins that LEDs are connect to. 13 | * @param {Array} [_kwpins] - Array of tuples listing names for each pin eg [['red',17], ['amber',22]]. 14 | * @param {Object} [_options] - Set options for the Collection: 15 | * * pwm: Default: false, If true, creates PWMLED instances for each pin, else LED. 16 | * * active_high: Default: true, If true, the on method will set all the associated pins to HIGH. 17 | * If false, the on method will set all pins to LOW 18 | * (the `off` method always does the opposite). 19 | * * initial_value: If false, all LEDs will be off initially, if true the device will be Switched on initialled. 20 | * @augments CompositeOutputDevice 21 | * @class 22 | */ 23 | function LEDCollection(_pins, _kwpins, _options) { 24 | "use strict"; 25 | const defaults = { 26 | pwm: false, 27 | active_high: true, 28 | initial_value: false, 29 | }; 30 | this.options = extend(defaults, _options); 31 | this._leds = []; 32 | this._kwleds = []; 33 | let i; 34 | if (_pins !== undefined) { 35 | for (i = 0; i < _pins.length; i++) { 36 | this._leds.push(this.options.pwm ? new PWMLED(_pins[i]) : new LED(_pins[i])); 37 | } 38 | } 39 | 40 | if (_kwpins !== undefined) { 41 | for (i = 0; i < _kwpins.length; i++) { 42 | this._kwleds.push([ 43 | _kwpins[i][0], 44 | this.options.pwm ? new PWMLED(_kwpins[i][1]) : new LED(_kwpins[i][1]) 45 | ]); 46 | } 47 | } 48 | CompositeOutputDevice.call(this, this._leds, this._kwleds); 49 | } 50 | 51 | LEDCollection.prototype = inherit(CompositeOutputDevice.prototype); 52 | LEDCollection.prototype.constructor = LEDCollection; 53 | 54 | /** 55 | * @returns {Array} - A flat array of tuples of all LEDs contained in this collection (and all sub-collections). 56 | */ 57 | LEDCollection.prototype.leds = function (){ 58 | return this._leds; 59 | }; 60 | 61 | /** 62 | * 63 | * @returns {boolean} Indicates whether the device is active high (true) or low (false). 64 | */ 65 | LEDCollection.prototype.active_high = function (){ 66 | return this[0].active_high; 67 | }; -------------------------------------------------------------------------------- /gpiozero/boards/PiTraffic.js: -------------------------------------------------------------------------------- 1 | const TrafficLights = require ('./TrafficLights.js').TrafficLights; 2 | const inherit = require ('../tools.js').inherit; 3 | const extend = require ('../tools.js').extend; 4 | 5 | /** 6 | * Represents the {@link http://lowvoltagelabs.com/products/pi-traffic/|Low Voltage Labs PI-TRAFFIC} vertical traffic lights board when attached to GPIO pins 9, 10, and 11. 7 | * There's no need to specify the pins if the PI-TRAFFIC is connected to the default pins (9, 10, 11). 8 | * 9 | * @param {Object} [_options] - Device Options: 10 | * * pwm: default: false. If true, creates PWMLED instances, else LED. 11 | * * initial_value: default: false. If false, all LEDs will be off initially, if true the device will be switched on initialled. 12 | * @class 13 | * @augments TrafficLights 14 | */ 15 | function PiTraffic(_options){ 16 | "use strict"; 17 | const defaults = { 18 | pwm: false, 19 | initial_value: false 20 | }; 21 | this.options = extend(defaults, _options); 22 | TrafficLights.call(this, 9,10,11, this.options); 23 | } 24 | 25 | exports.PiTraffic = PiTraffic; 26 | PiTraffic.prototype = inherit(TrafficLights.prototype); 27 | PiTraffic.prototype.constructor = PiTraffic; -------------------------------------------------------------------------------- /gpiozero/boards/TrafficLights.js: -------------------------------------------------------------------------------- 1 | const LEDBoard = require ('./LEDBoard.js').LEDBoard; 2 | const inherit = require ('../tools.js').inherit; 3 | const extend = require ('../tools.js').extend; 4 | const exc = require('../exc.js'); 5 | 6 | exports.TrafficLights = TrafficLights; 7 | 8 | /** 9 | * Represents a traffic light device containing red, amber, and green LEDs. 10 | * 11 | * @param {number} red - The GPIO pin that the red LED is attached to. 12 | * @param {number} amber - The GPIO pin that the amber LED is attached to. 13 | * @param {number} green - The GPIO pin that the green LED is attached to. 14 | * @param {Object} [_options] - Options for device: 15 | * * pwm: default: false. If true, creates PWMLED instances, else LED. 16 | * * initial_value: default: false. If false, all LEDs will be off initially, if true the device will be switched on initialled. 17 | * @augments LEDBoards 18 | * @class 19 | */ 20 | function TrafficLights(red, amber, green, _options) { 21 | "use strict"; 22 | const defaults = { 23 | pwm: false, 24 | initial_value: false 25 | }; 26 | this.options = extend(defaults, _options); 27 | 28 | if (red === undefined || 29 | amber === undefined || 30 | green === undefined) { 31 | throw new exc.GPIOPinMissing('Pins must be provided for all LEDs'); 32 | } 33 | this.devices = [['red', red],['amber',amber],['green',green]]; 34 | LEDBoard.call(this,undefined, this.devices, this.options); 35 | } 36 | 37 | TrafficLights.prototype = inherit(LEDBoard.prototype); 38 | TrafficLights.prototype.constructor = TrafficLights; -------------------------------------------------------------------------------- /gpiozero/compat.js: -------------------------------------------------------------------------------- 1 | var exc = require('./exc.js'); 2 | 3 | 4 | // ported from python 3.5; see 5 | // github.com/PythonCHB/close_pep/blob/master/is_close.py for original 6 | // implementation 7 | function isclose(a, b, rel_tol, abs_tol) { 8 | abs_tol = (abs_tol === undefined? 0.0 : abs_tol); 9 | rel_tol = (rel_tol === undefined? 1e-9 : rel_tol); 10 | 11 | if (rel_tol < 0.0 || abs_tol < 0.0) { 12 | throw exc.ValueError('error tolerances must be non-negative'); 13 | } 14 | 15 | if (a === b) { // fast-path for exact equality 16 | return true; 17 | } 18 | if (!isFinite(a) || !isFinite(b)){ 19 | return false; 20 | } 21 | var diff = Math.abs(b - a); 22 | return ( 23 | (diff <= Math.abs(rel_tol * b)) || 24 | (diff <= Math.abs(rel_tol * a)) || 25 | (diff <= abs_tol) 26 | ); 27 | } 28 | 29 | exports.isclose = isclose; -------------------------------------------------------------------------------- /gpiozero/devices/CompositeDevice.js: -------------------------------------------------------------------------------- 1 | const Device = require ('./Device.js').Device; 2 | const inherit = require('../tools.js').inherit; 3 | 4 | /** 5 | * Represents a device composed of multiple devices like simple HATs, H-bridge motor controllers, robots composed of multiple motors, etc. 6 | * The constructor accepts subordinate devices as positional or keyword arguments. 7 | * Positional arguments form unnamed devices accessed via the (@link CompositeDevice#all|all) attribute, 8 | * while keyword arguments are added to the device as named attributes. 9 | * 10 | * @param {Array} devices - An Array of positional devices. 11 | * @param {Array} kwdevices - An Array of tuples containing device name and device. 12 | * @class 13 | * @augments Device 14 | */ 15 | function CompositeDevice(devices, kwdevices) { 16 | this._all = []; 17 | this._namedtuple = []; 18 | let i; 19 | if(devices !== undefined) { 20 | for (i = 0; i < devices.length; i++) { 21 | this[i] = devices[i]; 22 | this._namedtuple.push('_' + i); 23 | this._all.push(devices[i]); 24 | } 25 | } 26 | 27 | if(kwdevices !== undefined) { 28 | for (i = 0; i < kwdevices.length; i++) { 29 | const device_name = kwdevices[i][0]; 30 | this[device_name] = kwdevices[i][1]; 31 | this._namedtuple.push(kwdevices[i][0]); 32 | this._all.push(kwdevices[i][1]); 33 | } 34 | } 35 | Device.call(this); 36 | } 37 | 38 | CompositeDevice.prototype = inherit(Device.prototype); 39 | CompositeDevice.prototype.constructor = CompositeDevice; 40 | 41 | /** 42 | * 43 | * @returns {number} - The number of subordinate devices. 44 | */ 45 | CompositeDevice.prototype.length = function() { 46 | return this._all.length; 47 | }; 48 | 49 | /** 50 | * 51 | * @returns {Array} - An array of subordinate device names. 52 | */ 53 | CompositeDevice.prototype.namedtuple = function() { 54 | return this._namedtuple; 55 | }; 56 | 57 | /** 58 | * 59 | * @returns {Array} - An array of all subordinate device values. 60 | */ 61 | CompositeDevice.prototype.value = function () { 62 | let i; 63 | const result = []; 64 | for (i = 0; i < this._all.length; i++) { 65 | result[i] = this._all[i].value(); 66 | } 67 | return result; 68 | }; 69 | 70 | /** 71 | * 72 | * @returns {boolean} - An array of each subordinate devices active state. 73 | */ 74 | CompositeDevice.prototype.is_active = function () { 75 | let i; 76 | for (i = 0; i < this._all.length; i++) { 77 | if (this._all[i].value()) { 78 | return true; 79 | } 80 | } 81 | return false; 82 | }; 83 | 84 | /** 85 | * Close all subordinate devices. 86 | */ 87 | CompositeDevice.prototype.close = function () { 88 | this._all.forEach((device) => { 89 | device.close(); 90 | }); 91 | }; 92 | 93 | exports.CompositeDevice = CompositeDevice; 94 | /* 95 | class CompositeDevice(Device): 96 | 97 | :param list _order: 98 | If specified, this is the order of named items specified by keyword 99 | arguments (to ensure that the :attr:`value` tuple is constructed with a 100 | specific order). All keyword arguments *must* be included in the 101 | collection. If omitted, an alphabetically sorted order will be selected 102 | for keyword arguments. 103 | """ 104 | def __init__(self, *args, **kwargs): 105 | self._all = () 106 | self._named = frozendict({}) 107 | self._namedtuple = None 108 | self._order = kwargs.pop('_order', None) 109 | if self._order is None: 110 | self._order = sorted(kwargs.keys()) 111 | else: 112 | for missing_name in set(kwargs.keys()) - set(self._order): 113 | raise CompositeDeviceBadOrder('%s missing from _order' % missing_name) 114 | self._order = tuple(self._order) 115 | super(CompositeDevice, self).__init__() 116 | for name in set(self._order) & set(dir(self)): 117 | raise CompositeDeviceBadName('%s is a reserved name' % name) 118 | self._all = args + tuple(kwargs[v] for v in self._order) 119 | for dev in self._all: 120 | if not isinstance(dev, Device): 121 | raise CompositeDeviceBadDevice("%s doesn't inherit from Device" % dev) 122 | self._named = frozendict(kwargs) 123 | self._namedtuple = namedtuple('%sValue' % self.__class__.__name__, chain( 124 | (str(i) for i in range(len(args))), self._order), 125 | rename=True) 126 | 127 | def __getattr__(self, name): 128 | # if _named doesn't exist yet, pretend it's an empty dict 129 | if name == '_named': 130 | return frozendict({}) 131 | try: 132 | return self._named[name] 133 | except KeyError: 134 | raise AttributeError("no such attribute %s" % name) 135 | 136 | def __setattr__(self, name, value): 137 | # make named components read-only properties 138 | if name in self._named: 139 | raise AttributeError("can't set attribute %s" % name) 140 | return super(CompositeDevice, self).__setattr__(name, value) 141 | 142 | def __repr__(self): 143 | try: 144 | self._check_open() 145 | return "" % ( 146 | self.__class__.__name__, 147 | len(self), ','.join(self._order), 148 | len(self) - len(self._named) 149 | ) 150 | except DeviceClosed: 151 | return "" % (self.__class__.__name__) 152 | 153 | def __getitem__(self, index): 154 | return self._all[index] 155 | 156 | def __iter__(self): 157 | return iter(self._all) 158 | 159 | @property 160 | def all(self): 161 | # XXX Deprecate this in favour of using the instance as a container 162 | return self._all 163 | 164 | def close(self): 165 | if self._all: 166 | for device in self._all: 167 | device.close() 168 | 169 | @property 170 | def closed(self): 171 | return all(device.closed for device in self) 172 | 173 | @property 174 | def namedtuple(self): 175 | return self._namedtuple 176 | 177 | @property 178 | def value(self): 179 | return self.namedtuple(*(device.value for device in self)) 180 | 181 | @property 182 | def is_active(self): 183 | return any(self.value) 184 | 185 | */ -------------------------------------------------------------------------------- /gpiozero/devices/Device.js: -------------------------------------------------------------------------------- 1 | const exc = require('../exc.js'); 2 | 3 | /** 4 | * Represents a single device of any type; GPIO-based, SPI-based, I2C-based, 5 | * etc. This is the base class of the device hierarchy. It defines the 6 | * basic services applicable to all devices (specifically the {@link Device#is_active|is_active} 7 | * property, the {@link Device#value|value} property, and the {@link Device#close|close} method). 8 | * 9 | * @class 10 | */ 11 | function Device() { 12 | // eslint-disable-next-line no-empty-function 13 | } 14 | /** 15 | * Returns a value representing the device's state. Frequently, this is a 16 | * boolean value, or a number between 0 and 1 but some devices use larger 17 | * ranges (e.g. -1 to +1) and composite devices usually use tuples to 18 | * return the states of all their subordinate components. 19 | */ 20 | Device.prototype.value = function() { 21 | 22 | throw new exc.NotImplementedError(); 23 | }; 24 | 25 | /** 26 | * Returns `true` if the device is currently active and `false` 27 | * otherwise. This property is usually derived from `value` attribute. Unlike 28 | * `value` attribute, this is *always* a boolean. 29 | */ 30 | Device.prototype.is_active = function() { 31 | 32 | return (this.value !== undefined); 33 | }; 34 | /** 35 | * Internal method to check if device is available. 36 | * 37 | * @private 38 | */ 39 | Device.prototype._check_open = function() { 40 | if (this.closed()) { 41 | throw new exc.DeviceClosed('is closed or uninitialized'); 42 | } 43 | }; 44 | /** 45 | * @abstract 46 | */ 47 | Device.prototype.close = function() { 48 | return; 49 | }; 50 | 51 | exports.Device = Device; -------------------------------------------------------------------------------- /gpiozero/devices/GPIODevice.js: -------------------------------------------------------------------------------- 1 | const Device = require ('./Device.js').Device; 2 | const inherit = require('../tools.js').inherit; 3 | const wiringpi = require('../pins/wiringpi.js').WiringPiPin; 4 | const ReadWriteLock = require('rwlock'); 5 | const exc = require('../exc.js'); 6 | 7 | const _PINS = new Set(); 8 | const _PINS_LOCK = new ReadWriteLock(); //Yes, this needs to be re-entrant 9 | 10 | /* /*if(name == undefined) { 11 | name=process.env.GPIOZERO_PIN_FACTORY; 12 | } 13 | var group = 'gpiozero_pin_factories' 14 | if (name == undefined) { 15 | /*# If no factory is explicitly specified, try various names in 16 | # "preferred" order. Note that in this case we only select from 17 | # gpiozero distribution so without explicitly specifying a name (via 18 | # the environment) it's impossible to auto-select a factory from 19 | # outside the base distribution 20 | # 21 | # We prefer RPi.GPIO here as it supports PWM, and all Pi revisions. If 22 | # no third-party libraries are available, however, we fall back to a 23 | # pure Python implementation which supports platforms like PyPy 24 | dist = pkg_resources.get_distribution('gpiozero') 25 | for name in ('RPiGPIOPin', 'RPIOPin', 'PiGPIOPin', 'NativePin'): 26 | try: 27 | return pkg_resources.load_entry_point(dist, group, name) 28 | except ImportError: 29 | pass 30 | raise BadPinFactory('Unable to locate any default pin factory!') 31 | } else { 32 | for factory in pkg_resources.iter_entry_points(group, name): 33 | return factory.load() 34 | raise BadPinFactory('Unable to locate pin factory "%s"' % name) 35 | }*/ 36 | 37 | //} 38 | 39 | 40 | //var pin_factory = _default_pin_factory(); 41 | 42 | /** 43 | * Represents a generic GPIO device and provides the services common to all single-pin GPIO devices 44 | * (like ensuring two GPIO devices do no share a {@link Pin}). 45 | * 46 | * @param {(int | Pin)} pin - The GPIO pin (in BCM numbering) or a instance of {@link Pin} that the device is connected to. 47 | * 48 | * @throws {GPIOPinMissing} - If pin is 'undefined' 49 | * @throws {GPIOPinInUse} - If the pin is already in use by another device 50 | * @class 51 | * @augments Device 52 | */ 53 | function GPIODevice(pin) { 54 | Device.call(this); 55 | this._pin = undefined; 56 | if (pin === undefined) { 57 | throw new exc.GPIOPinMissing('No pin given'); 58 | } 59 | if (Number.isInteger(pin)) { 60 | pin = new wiringpi(pin); 61 | } 62 | 63 | _PINS_LOCK.readLock((release) => { 64 | if (_PINS.has(pin)) { 65 | throw new exc.GPIOPinInUse('pin ' + pin.toString() + ' is already in use by another gpiozero object'); 66 | } 67 | _PINS.add(pin); 68 | release(); 69 | }); 70 | 71 | this._pin = pin; 72 | this._active_state = true; 73 | this._inactive_state = false; 74 | } 75 | 76 | GPIODevice.prototype = inherit(Device.prototype); 77 | GPIODevice.prototype.constructor = GPIODevice; 78 | 79 | /** 80 | * Close the device and remove the pin allocation allowing it to be reused. 81 | */ 82 | GPIODevice.prototype.close = function() { 83 | const that = this; 84 | _PINS_LOCK.readLock((release) => { 85 | const pin = that._pin; 86 | if (_PINS.has(pin)) { 87 | _PINS.delete(pin); 88 | that._pin.close(); 89 | } 90 | that._pin = undefined; 91 | release(); 92 | }); 93 | }; 94 | 95 | /** 96 | * 97 | * @returns {boolean} - Is ``true`` is no pin is allocated. 98 | */ 99 | GPIODevice.prototype.closed = function() { 100 | return (this._pin === undefined); 101 | }; 102 | 103 | /** 104 | * 105 | * @returns {undefined|*|int|Pin} - The {@link Pin} that the device is connected to. This will be ``undefined`` 106 | * if the device has been closed (see the :meth:`close` method). When dealing with GPIO pins, query ``pin.number`` 107 | * to discover the GPIO pin (in BCM numbering) that the device is connected to. 108 | */ 109 | GPIODevice.prototype.pin = function() { 110 | return this._pin; 111 | }; 112 | 113 | /** 114 | * @returns {int|Boolean} - Current value of the pin. 115 | */ 116 | GPIODevice.prototype.value = function() { 117 | return this._read(); 118 | }; 119 | 120 | /** 121 | * Internal method to read the pin value. 122 | * 123 | * @private 124 | */ 125 | GPIODevice.prototype._read = function() { 126 | this._check_open(); 127 | return this._state_to_value(this.pin().state()); 128 | }; 129 | 130 | /** 131 | * Internal method to apply active state high and convert the actual value to a logical value. 132 | * 133 | * @param {boolean|float} state - The value to be converted. 134 | * @returns {boolean} - The logical value of the pin. 135 | * @private 136 | */ 137 | GPIODevice.prototype._state_to_value = function(state) { 138 | return Boolean(state === this._active_state); 139 | }; 140 | /** 141 | * 142 | * @returns {boolean} - Is true is the device value is currently set. 143 | */ 144 | GPIODevice.prototype.is_active = function() { 145 | return Boolean(this.value()); 146 | }; 147 | 148 | /** 149 | * 150 | * @returns {string} - Description of the device. 151 | */ 152 | GPIODevice.prototype.toString = function() { 153 | return ""; 154 | }; 155 | 156 | exports.GPIODevice = GPIODevice; -------------------------------------------------------------------------------- /gpiozero/exc.js: -------------------------------------------------------------------------------- 1 | var inherit = require ('./tools.js').inherit; 2 | 3 | function NotImplementedError (message) { 4 | message = message !== undefined?message:"The method is not yet implemented"; 5 | Error.call(this, message); 6 | } 7 | 8 | NotImplementedError.prototype = inherit(Error.prototype); 9 | NotImplementedError.prototype.constructor = NotImplementedError; 10 | 11 | exports.NotImplementedError = NotImplementedError; 12 | 13 | function GPIOZeroError (message) { 14 | message = message !== undefined?message:"Base class for all exceptions in GPIO Zero"; 15 | Error.call(this, message); 16 | } 17 | 18 | GPIOZeroError.prototype = inherit(Error.prototype); 19 | GPIOZeroError.prototype.constructor = GPIOZeroError; 20 | 21 | /*var NotImplementedError = GPIOZeroError.extend({ 22 | init : function (message){ 23 | this._super(message!=undefined?message:"Function not Implemented"); 24 | } 25 | });*/ 26 | 27 | function GPIODeviceError (message) { 28 | GPIOZeroError.call(this, message !== undefined ? message:"Base class for errors specific to the GPIODevice hierarchy"); 29 | } 30 | GPIODeviceError.prototype = inherit(GPIOZeroError.prototype); 31 | GPIODeviceError.prototype.constructor = GPIODeviceError; 32 | 33 | function DeviceClosed (message) { 34 | GPIOZeroError.call(this, message !== undefined ? message:"Base class for errors specific to the GPIODevice hierarchy"); 35 | } 36 | DeviceClosed.prototype = inherit(GPIOZeroError.prototype); 37 | DeviceClosed.prototype.constructor = DeviceClosed; 38 | exports.DeviceClosed = DeviceClosed; 39 | 40 | function GPIOPinMissing (message) { 41 | GPIODeviceError.call(this, message !== undefined ? message:"Error raised when a pin number is not specified"); 42 | } 43 | GPIOPinMissing.prototype = inherit(GPIODeviceError.prototype); 44 | GPIOPinMissing.prototype.constructor = GPIOPinMissing; 45 | exports.GPIOPinMissing = GPIOPinMissing; 46 | 47 | 48 | function GPIOPinInUse (message) { 49 | GPIODeviceError.call(this, message !== undefined?message:"Error raised when attempting to use a pin already in use by another device"); 50 | } 51 | GPIOPinInUse.prototype = inherit(GPIODeviceError.prototype); 52 | GPIOPinInUse.prototype.constructor = GPIOPinInUse; 53 | exports.GPIOPinInUse = GPIOPinInUse; 54 | 55 | function PinError(message) { 56 | GPIOZeroError.call(this, message !== undefined?message:"Base class for errors related to pin implementations"); 57 | } 58 | PinError.prototype = inherit(GPIOZeroError.prototype); 59 | PinError.prototype.constructor = PinError; 60 | 61 | function PinInvalidFunction (message) { 62 | PinError.call(this, message); 63 | } 64 | PinInvalidFunction.prototype = inherit(PinError.prototype); 65 | PinInvalidFunction.prototype.constructor = PinInvalidFunction; 66 | 67 | function PinSetInput (message) { 68 | PinError.call(this, message); 69 | } 70 | PinSetInput.prototype = inherit(PinError.prototype); 71 | PinSetInput.prototype.constructor = PinSetInput; 72 | exports.PinSetInput = PinSetInput; 73 | 74 | function OutputDeviceError (message) { 75 | GPIOZeroError.call(this, message !== undefined?message:"Base class for errors specific to the GPIODevice hierarchy"); 76 | } 77 | OutputDeviceError.prototype = inherit(GPIOZeroError.prototype); 78 | OutputDeviceError.prototype.constructor = OutputDeviceError; 79 | 80 | function OutputDeviceBadValue(message){ 81 | OutputDeviceError.call(this, message !== undefined?message:"Error Raised when unacceptable value receieved"); 82 | } 83 | OutputDeviceBadValue.prototype = inherit(OutputDeviceError.prototype); 84 | OutputDeviceBadValue.prototype.constructor = OutputDeviceBadValue; 85 | exports.OutputDeviceBadValue = OutputDeviceBadValue; 86 | 87 | function AttributeError (message) { 88 | GPIOZeroError.call(this, message !== undefined?message:"Base class for attribute errors"); 89 | } 90 | AttributeError.prototype = inherit(GPIOZeroError.prototype); 91 | AttributeError.prototype.constructor = AttributeError; 92 | 93 | function PinPWMUnsupported(message) { 94 | AttributeError.call(this, message !== undefined?message:"PWM Not Support in this Pin"); 95 | } 96 | 97 | PinPWMUnsupported.prototype = inherit(AttributeError.prototype); 98 | PinPWMUnsupported.prototype.constructor = PinPWMUnsupported; 99 | exports.PinPWMUnsupported = PinPWMUnsupported; 100 | 101 | function PinFixedPull(message) { 102 | AttributeError.call(this, message !== undefined?message:"PError raised when attempting to set the pull of a pin with fixed pull-up"); 103 | } 104 | 105 | PinFixedPull.prototype = inherit(AttributeError.prototype); 106 | PinPWMUnsupported.prototype.constructor = PinFixedPull; 107 | exports.PinFixedPull = PinFixedPull; -------------------------------------------------------------------------------- /gpiozero/index.js: -------------------------------------------------------------------------------- 1 | const exc = require('./exc.js'); 2 | const GPIODeviceClass = require('./devices/GPIODevice.js').GPIODevice; 3 | const CompositeDeviceClass = require('./devices/CompositeDevice.js').CompositeDevice; 4 | const OutputDeviceClass = require ('./output_devices/OutputDevice.js').OutputDevice; 5 | const DigitalOutputDeviceClass = require ('./output_devices/DigitalOutputDevice.js').DigitalOutputDevice; 6 | const PWMOutputDeviceClass = require ('./output_devices/PWMOutputDevice.js').PWMOutputDevice; 7 | const CompositeOutputDeviceClass = require('./output_devices/CompositeOutputDevice.js').CompositeOutputDevice; 8 | const InputDeviceClass = require ('./input_devices/InputDevice.js').InputDevice; 9 | const DigitalInputDeviceClass = require ('./input_devices/DigitalInputDevice.js').DigitalInputDevice; 10 | const LEDClass = require ('./output_devices/LED.js').LED; 11 | const RGBLEDClass = require ('./output_devices/RGBLED.js').RGBLED; 12 | const PWMLEDClass = require ('./output_devices/PWMLED.js').PWMLED; 13 | const BuzzerClass = require ('./output_devices/Buzzer.js').Buzzer; 14 | const MotorClass = require ('./output_devices/Motor.js').Motor; 15 | const tools = require('./tools.js'); 16 | const TrafficLightsClass = require('./boards/TrafficLights.js').TrafficLights; 17 | const PiTrafficClass = require('./boards/PiTraffic.js').PiTraffic; 18 | 19 | //noinspection JSUnresolvedVariable 20 | module.exports = { 21 | GPIOPinInUse : exc.GPIOPinInUse 22 | ,GPIOPinMissing : exc.GPIOPinMissing 23 | ,OutputDeviceBadValue : exc.OutputDeviceBadValue 24 | ,PinPWMUnsupported : exc.PinPWMUnsupported 25 | ,PinInputState : exc.PinInputState 26 | ,PinFixedPull : exc.PinFixedPull 27 | 28 | ,CompositeDevice : CompositeDeviceClass 29 | ,GPIODevice : GPIODeviceClass 30 | 31 | 32 | ,OutputDevice : OutputDeviceClass 33 | ,DigitalOutputDevice: DigitalOutputDeviceClass 34 | ,PWMOutputDevice : PWMOutputDeviceClass 35 | ,CompositeOutputDevice : CompositeOutputDeviceClass 36 | 37 | ,InputDevice : InputDeviceClass 38 | ,DigitalInputDevice : DigitalInputDeviceClass 39 | 40 | ,LED : LEDClass 41 | ,Buzzer : BuzzerClass 42 | ,Motor : MotorClass 43 | ,PWMLED : PWMLEDClass 44 | ,RGBLED : RGBLEDClass 45 | 46 | ,TrafficLights : TrafficLightsClass 47 | ,PiTraffic: PiTrafficClass 48 | 49 | ,with_close : tools.with_close 50 | ,inherit : tools.inherit 51 | }; 52 | -------------------------------------------------------------------------------- /gpiozero/input_devices/DigitalInputDevice.js: -------------------------------------------------------------------------------- 1 | const InputDevice = require('./InputDevice.js').InputDevice; 2 | const inherit = require('../tools.js').inherit; 3 | const _extend_object = require('../tools.js')._extend_object; 4 | const EventsMixin = require ('../Mixins/EventsMixin.js').EventsMixin; 5 | 6 | exports.DigitalInputDevice = DigitalInputDevice; 7 | 8 | /** 9 | * Represents a generic input device with typical on/off behaviour. 10 | * 11 | * This class extends {@link InputDevice|InputDevice} with machinery to fire the active 12 | * and inactive events for devices that operate in a typical digital manner 13 | * straight forward on / off states with (reasonably) clean transitions between the two. 14 | * 15 | * @param {int} pin - The GPIO pin (in Broadcom numbering) that the device is connected to. 16 | * @param {boolean} [pull_up] - If `true`, the pin will be pulled high with an internal resistor. If 17 | * `false` (the default), the pin will be pulled low. 18 | * @param {float} [bounce_time] - Specifies the length of time (in seconds) that the component will 19 | * ignore changes in state after an initial change. This defaults to 20 | * `undefined` which indicates that no bounce compensation will be performed. 21 | * @class 22 | * @augments InputDevice 23 | */ 24 | function DigitalInputDevice(pin, pull_up, bounce_time) { 25 | InputDevice.call(this, pin, pull_up); 26 | _extend_object(this, EventsMixin.prototype); 27 | EventsMixin.call(this); 28 | this._pin.bounce = bounce_time; 29 | this._pin.edges = 'both'; 30 | const that = this; 31 | this._pin.when_changed( ()=>{ that._fire_events();}); 32 | //Call _fire_events once to set initial state of events 33 | this._fire_events(); 34 | 35 | } 36 | 37 | DigitalInputDevice.prototype = inherit(InputDevice.prototype); 38 | DigitalInputDevice.prototype.constructor = DigitalInputDevice; -------------------------------------------------------------------------------- /gpiozero/input_devices/InputDevice.js: -------------------------------------------------------------------------------- 1 | const GPIODevice = require('../devices/GPIODevice.js').GPIODevice; 2 | const inherit = require('../tools.js').inherit; 3 | 4 | exports.InputDevice = InputDevice; 5 | 6 | /** 7 | * Represents a generic GPIO input device. 8 | * This class extends {@link GPIODevice} to add facilities common to GPIO 9 | * input devices. The constructor adds the optional *pull_up* parameter to 10 | * specify how the pin should be pulled by the internal resistors. The 11 | * {@link InputDevice#is_active|is_active} property is adjusted accordingly so that 12 | * ``true`` still means active regardless of the {@link InputDevice#pull_up|pullup} setting. 13 | * 14 | * @param {int | Pin} pin - The GPIO pin (in Broadcom numbering) that the device is connected to. 15 | * @param {boolean} [pullup] - If ``true``, the pin will be pulled high with an internal resistor. If 16 | * ``false`` (the default), the pin will be pulled low. 17 | * @class 18 | * @augments GPIODevice 19 | * @throws GPIODeviceError 20 | */ 21 | function InputDevice (pin, pullup) { 22 | GPIODevice.call(this, pin); 23 | 24 | if (typeof pullup === 'undefined') { 25 | pullup = false; 26 | } 27 | 28 | const pull = pullup ? 'up' : 'down'; 29 | if (this._pin.pull() !== pull) { 30 | this._pin.pull(pull); 31 | } 32 | this._active_state = !pullup; 33 | this._inactive_state = pullup; 34 | } 35 | 36 | InputDevice.prototype = inherit(GPIODevice.prototype); 37 | InputDevice.prototype.constructor = InputDevice; 38 | 39 | /** 40 | * If ``true``, the device uses a pull-up resistor to set the GPIO pin "high" by default. 41 | */ 42 | InputDevice.prototype.pull_up = function () { 43 | return (this._pin.pull() === 'up'); 44 | }; 45 | 46 | InputDevice.prototype.toString = function () { 47 | return ''; 48 | } -------------------------------------------------------------------------------- /gpiozero/output_devices/Buzzer.js: -------------------------------------------------------------------------------- 1 | const inherit = require('../tools.js').inherit; 2 | const DigitalOutputDevice = require('./DigitalOutputDevice.js').DigitalOutputDevice; 3 | 4 | exports.Buzzer = Buzzer; 5 | /** 6 | * Represents a digital buzzer component. 7 | * 8 | * @example const Buzzer = require ('gpiozero').Buzzer; 9 | * bz = new Buzzer(3); 10 | * bz.on(); 11 | * 12 | * @param {int | Pin} pin - The GPIO pin which the buzzer is attached to. 13 | * @param {boolean} active_high - If ``true`` (the default), the buzzer will operate normally with the circuit described above. 14 | * If ``false`` you should wire the cathode to the GPIO pin, and the anode to a 3V3 pin. 15 | * @param {boolean} initial_value - If ``false`` (the default), the buzzer will be silent initially. 16 | * If ``undefined``, the buzzer will be left in whatever state the pin is found in 17 | * when configured for output (warning: this can be on). If ``true``, the buzzer will be switched on initially. 18 | * @class 19 | * @augments DigitalOutputDevice 20 | */ 21 | function Buzzer(pin, active_high, initial_value) { 22 | DigitalOutputDevice.call(this, pin, active_high, initial_value); 23 | } 24 | 25 | Buzzer.prototype = inherit(DigitalOutputDevice.prototype); 26 | Buzzer.prototype.constructor = Buzzer; 27 | 28 | /** 29 | * Make the buzzer switch on and off once a second. 30 | */ 31 | Buzzer.prototype.beep = function() { 32 | this.blink(); 33 | }; 34 | 35 | -------------------------------------------------------------------------------- /gpiozero/output_devices/CompositeOutputDevice.js: -------------------------------------------------------------------------------- 1 | const exc = require('../exc.js'); 2 | const CompositeDevice = require('../devices/CompositeDevice.js').CompositeDevice; 3 | const OutputDevice = require('../output_devices/OutputDevice.js').OutputDevice; 4 | const inherit = require('../tools.js').inherit; 5 | 6 | /** 7 | * Extends {@link CompositeDevice} with {@link CompositeDevice#on|on}, {@link CompositeDevice#off|off}, 8 | * and {@link CompositeDevice#toggle|toggle} methods for controlling subordinate output devices 9 | * and extends {@link CompositeDevice#value|value} to be writable. 10 | * 11 | * @param {Array} [devices] - An array of devices that create this composite device. 12 | * @param {Array} [kwdevices] - An array of tuples that contain the device name and device eg ['red', new LED(1)]. 13 | * @param {Array} [options] - 14 | * @augments CompositeDevice 15 | * @class 16 | */ 17 | function CompositeOutputDevice (devices, kwdevices, options) { 18 | "use strict"; 19 | CompositeDevice.call(this, devices, kwdevices, options); 20 | } 21 | 22 | CompositeOutputDevice.prototype = inherit(CompositeDevice.prototype); 23 | CompositeOutputDevice.prototype.constructor = CompositeOutputDevice; 24 | 25 | exports.CompositeOutputDevice = CompositeOutputDevice; 26 | 27 | /** 28 | * Calls the on method on all child devices within this composite device. 29 | */ 30 | CompositeOutputDevice.prototype.on = function () { 31 | this._all.forEach((device) => { 32 | if (device instanceof OutputDevice || device instanceof CompositeOutputDevice) { 33 | device.on(); 34 | } 35 | }); 36 | }; 37 | 38 | /** 39 | * Calls the off method on all child devices within this composite device. 40 | */ 41 | CompositeOutputDevice.prototype.off = function () { 42 | this._all.forEach((device) => { 43 | if (device instanceof OutputDevice || device instanceof CompositeOutputDevice) { 44 | device.off(); 45 | } 46 | }); 47 | }; 48 | 49 | 50 | /** 51 | * Calls the toggle method on all child devices within this composite device. 52 | **/ 53 | CompositeOutputDevice.prototype.toggle = function () { 54 | this._all.forEach((device) => { 55 | if (device instanceof OutputDevice || device instanceof CompositeOutputDevice) { 56 | device.toggle(); 57 | } 58 | }); 59 | }; 60 | 61 | /** 62 | * When value is undefined then the function returns the value of all child 63 | * devices as an array. 64 | * When value is set, all child devices will have their value set according 65 | * to the value array. 66 | * 67 | * @param {Array} [value] - The value to set all of the child devices to. 68 | * @returns {Array} - The current value of each output device returned as an array. 69 | */ 70 | CompositeOutputDevice.prototype.value = function (value) { 71 | if (value === undefined) { 72 | return CompositeDevice.prototype.value.call(this); 73 | } 74 | if (value.length !== this._all.length) { 75 | throw new exc.OutputDeviceError(); 76 | } 77 | let i = 0; 78 | for (i = 0; i 1 || value < -1) { 74 | throw new exc.OutputDeviceBadValue("Motor value must be between -1 and 1, actual=:" + value); 75 | } 76 | 77 | if (value > 0) { 78 | this.forward(value); 79 | } else if (value < 0) { 80 | this.backward(-value); 81 | } else { 82 | this.stop(); 83 | } 84 | }; 85 | /** 86 | * 87 | * @returns {boolean} - If the motor is currently running then ``true`` otherwise ``false``. 88 | */ 89 | Motor.prototype.is_active = function() { 90 | /* 91 | 92 | */ 93 | return this.value() !== 0; 94 | }; 95 | 96 | /** 97 | * Drive the motor forwards. 98 | * 99 | * @param {float} speed - The speed at which the motor should turn. Can be any value between 0 (stopped) 100 | * and the default 1 (maximum speed) if ``pwm`` was ``true`` when the class was constructed (and only 0 or 1 if not). 101 | * 102 | * @throws ValueError - When the speed is less than 0 or greater than 1. 103 | * @throws ValueError - When the speed is between 0 and 1 on non-pwm motors. 104 | */ 105 | Motor.prototype.forward = function(speed) { 106 | if (speed === undefined) { 107 | speed = 1; 108 | } 109 | 110 | if (speed < 0 || speed > 1) { 111 | throw new exc.ValueError('forward speed must be between 0 and 1'); 112 | } 113 | 114 | if (this.forward_device instanceof DigitalOutputDevice && speed !== 1 && speed !== 0) { 115 | throw new exc.ValueError('forward speed must be 0 or 1 with non-PWM Motors'); 116 | } 117 | 118 | this.backward_device.off(); 119 | this.forward_device.value(speed); 120 | }; 121 | 122 | /** 123 | * Drive the motor backwards. 124 | * 125 | * @param {float} speed - The speed at which the motor should turn. Can be any value between 0 (stopped) 126 | * and the default 1 (maximum speed) if ``pwm`` was ``true`` when the class was constructed (and only 0 or 1 if not). 127 | * 128 | * @throws ValueError - When the speed is less than 0 or greater than 1. 129 | * @throws ValueError - When the speed is between 0 and 1 on non-pwm motors. 130 | */ 131 | Motor.prototype.backward = function(speed) { 132 | if (speed === undefined) { 133 | speed = 1; 134 | } 135 | 136 | if (speed < 0 || speed > 1) { 137 | throw new exc.ValueError('backward speed must be between 0 and 1'); 138 | } 139 | 140 | if (this.backward_device instanceof DigitalOutputDevice && speed !== 1 && speed !== 0) { 141 | throw new exc.ValueError('backward speed must be 0 or 1 with non-PWM Motors'); 142 | } 143 | 144 | this.forward_device.off(); 145 | this.backward_device.value(speed); 146 | }; 147 | 148 | /** 149 | * Reverse the current direction of the motor. If the motor is currently 150 | * idle this does nothing. Otherwise, the motor's direction will be 151 | * reversed at the current speed. 152 | */ 153 | Motor.prototype.reverse = function() { 154 | this.value(-1 * this.value()); 155 | }; 156 | 157 | /** 158 | * Stop the motor. 159 | */ 160 | Motor.prototype.stop = function() { 161 | this.forward_device.off(); 162 | this.backward_device.off(); 163 | }; 164 | -------------------------------------------------------------------------------- /gpiozero/output_devices/OutputDevice.js: -------------------------------------------------------------------------------- 1 | const GPIODevice = require('../devices/GPIODevice.js').GPIODevice; 2 | const Lock = require('rwlock'); 3 | const inherit = require('../tools.js').inherit; 4 | 5 | exports.OutputDevice = OutputDevice; 6 | /** 7 | * Represents a generic GPIO output device. 8 | * Provides facilities common to GPIO output devices an {@link OutputDevice#on|on} method to switch the device on, a 9 | * corresponding {@link OutputDevice#off|off} method, and a {@link OutputDevice#toggle|toggle} method. 10 | * 11 | * @param {(int | Pin)} pin - The GPIO pin (in BCM numbering) or an instance of Pin that the device is connected to. 12 | * @param {boolean} [active_high] - If `true` (the default), the {@link OutputDevice#on|on} method will set the GPIO to HIGH. 13 | * If `false`, the :{@link OutputDevice#on|on} method will set the GPIO to LOW (the {@link OutputDevice#off|off} method always does the opposite). 14 | * @param {boolean} [initial_value] - If `false` (the default), the device will be off initially. 15 | * If `undefined`, the device will be left in whatever state the pin is found in when configured for output (warning: this can be on). If `true`, the device will be switched on initially. 16 | * 17 | * @throws GPIOPinMissing - When pin is undefined. 18 | * @class 19 | * @augments GPIODevice 20 | */ 21 | function OutputDevice(pin, active_high, initial_value) { 22 | GPIODevice.call(this, pin); 23 | this._lock = new Lock(); 24 | this.active_high((active_high === undefined) ? true : active_high); 25 | 26 | if (initial_value === undefined) { 27 | this._pin.pin_function('output'); 28 | } else { 29 | this._pin.output_with_state(this._value_to_state(initial_value)); 30 | } 31 | } 32 | 33 | 34 | OutputDevice.prototype = inherit(GPIODevice.prototype); 35 | OutputDevice.prototype.constructor = OutputDevice; 36 | 37 | /** 38 | * Internal method to apply active state high and convert the actual value to a logical value. 39 | * 40 | * @param {boolean|float} value - The value to be converted. 41 | * @returns {boolean} - The logical value of the pin. 42 | * @private 43 | */ 44 | OutputDevice.prototype._value_to_state = function(value) { 45 | return (value) ? this._active_state : this._inactive_state; 46 | }; 47 | 48 | /** 49 | * Internal method used to write to the pin after mapping the request value. 50 | * 51 | * @param {float | boolean} value - The logical value that the pin should be changed to. 52 | * @private 53 | */ 54 | OutputDevice.prototype._write = function(value) { 55 | this._check_open(this); 56 | this._pin.state(this._value_to_state(value)); 57 | }; 58 | 59 | /** 60 | * Turns the device on. 61 | **/ 62 | OutputDevice.prototype.on = function() { 63 | this._pin._stop_blink(); 64 | this._write(true); 65 | }; 66 | 67 | /** 68 | * Turns the device off. 69 | */ 70 | OutputDevice.prototype.off = function() { 71 | this._pin._stop_blink(); 72 | this._write(false); 73 | }; 74 | 75 | /** 76 | * 77 | * This property can be set after construction; be warned that changing it 78 | * will invert {@link OutputDevice#value|value} (i.e. changing this property doesn't change 79 | * the device's pin state - it just changes how that state is interpreted). 80 | * 81 | * @param {boolean} [value] - When ``true``, the {@link OutputDevice#value|value} property is ``true`` when the device's 82 | * {@link OutputDevice#pin|pin} is high. When ``false`` the {@link OutputDevice#value|value} property is 83 | * ``true`` when the device's pin is low (i.e. the value is inverted). 84 | * 85 | */ 86 | OutputDevice.prototype.active_high = function(value) { 87 | if (value === undefined) { 88 | return this._active_state; 89 | } 90 | this._active_state = value; 91 | this._inactive_state = !value; 92 | }; 93 | 94 | /** 95 | * 96 | * @param {boolean | float} [value] - When supplied the device output is changed to the value. 97 | * @returns {boolean | float} - When value is undefined, the function returns the current value of the device. 98 | */ 99 | OutputDevice.prototype.value = function(value) { 100 | if (value === undefined) { 101 | return this._read(); 102 | } 103 | this._pin._stop_blink(); 104 | this._write(value); 105 | }; 106 | 107 | /** 108 | * Reverse the state of the device. If it's on, turn it off; if it's off, turn it on. 109 | */ 110 | OutputDevice.prototype.toggle = function() { 111 | const that = this; 112 | this._lock.readLock((release) => { 113 | if (that.is_active()) { 114 | that.off(); 115 | } else { 116 | that.on(); 117 | } 118 | release(); 119 | }); 120 | }; 121 | -------------------------------------------------------------------------------- /gpiozero/output_devices/PWMLED.js: -------------------------------------------------------------------------------- 1 | const inherit = require('../tools.js').inherit; 2 | const PWMOutputDevice = require('./PWMOutputDevice.js').PWMOutputDevice; 3 | 4 | exports.PWMLED = PWMLED; 5 | 6 | /** 7 | * Represents a light emitting diode (LED) with variable brightness. 8 | * 9 | * A typical configuration of such a device is to connect a GPIO pin to the 10 | * anode (long leg) of the LED, and the cathode (short leg) to ground, with 11 | * an optional resistor to prevent the LED from burning out. 12 | * 13 | * @param {int} pin - The GPIO pin which the LED is attached to. 14 | * @param {boolean} [active_high] - If ``true`` (the default), the {@link PWMLED#on|on} method will set the GPIO to HIGH. 15 | * If ``false``, the {@link PWMLED#on|on} method will set the GPIO to LOW (the {@link PWMLED#off|off} method always does 16 | * the opposite). 17 | * @param {float} [initial_value] - If ``0`` (the default), the LED will be off initially. Other values 18 | * between 0 and 1 can be specified as an initial brightness for the LED. Note that ``undefined`` cannot be specified 19 | * (unlike the parent class) as there is no way to tell PWM not to alter the state of the pin. 20 | * @param {int} [frequency] - The frequency (in Hz) of pulses emitted to drive the LED. Defaults to 100Hz. 21 | * @class 22 | * @augments PWMOutputDevice 23 | */ 24 | function PWMLED(pin, active_high, initial_value, frequency) { 25 | PWMOutputDevice.call(this, pin, active_high, initial_value, frequency); 26 | } 27 | 28 | PWMLED.prototype = inherit(PWMOutputDevice.prototype); 29 | PWMLED.prototype.constructor = PWMLED; 30 | 31 | /** 32 | * 33 | * @returns {boolean} - Alias for {@link PWMOutputDevice#is_active|is_active}. 34 | */ 35 | PWMLED.prototype.is_lit = function() { 36 | return this.is_active(); 37 | }; 38 | -------------------------------------------------------------------------------- /gpiozero/output_devices/PWMOutputDevice.js: -------------------------------------------------------------------------------- 1 | const inherit = require('../tools.js').inherit; 2 | const OutputDevice = require('./OutputDevice.js').OutputDevice; 3 | const exc = require('../exc.js'); 4 | 5 | exports.PWMOutputDevice = PWMOutputDevice; 6 | 7 | /** 8 | * Generic output device configured for pulse-width modulation (PWM). 9 | * 10 | * @param {int | Pin} pin - The GPIO pin which the device is attached to. 11 | * @param {boolean} active_high - If ``true`` (the default), the {@link PWMOutputDevice#on|on} method will set the GPIO to HIGH. 12 | * If ``false``, the {@link PWMOutputDevice#on|on} method will set the GPIO to LOW (the {@link PWMOutputDevice#off|off} method always does the opposite). 13 | * @param {int} initial_value - If ``0`` (the default), the device's duty cycle will be 0 initially. 14 | * Other values between 0 and 1 can be specified as an initial duty cycle. 15 | * Note that ``undefined`` cannot be specified (unlike the parent class) as there is no way to tell PWM not to alter the state of the pin. 16 | * @param {int} frequency - The frequency (in Hz) of pulses emitted to drive the device. Defaults to 100Hz. 17 | * @class 18 | * 19 | * @throws OutputDeviceBadValue - When intial_value is ``undefined``. 20 | */ 21 | function PWMOutputDevice(pin, active_high, initial_value, frequency) { 22 | if (initial_value !== undefined) { 23 | if (initial_value < 0 || initial_value > 1) { 24 | throw new exc.OutputDeviceBadValue("initial_value must be between 0 and 1, actual=:" + initial_value); 25 | } 26 | } 27 | 28 | OutputDevice.call(this, pin, active_high, initial_value); 29 | 30 | try { 31 | this._pin.frequency(frequency === undefined ? 100 : frequency); 32 | this.value(initial_value === undefined ? 0 : initial_value); 33 | } catch (e) { 34 | this.close(); 35 | throw e; 36 | } 37 | } 38 | 39 | PWMOutputDevice.prototype = inherit(OutputDevice.prototype); 40 | PWMOutputDevice.prototype.constructor = PWMOutputDevice; 41 | /** 42 | * The duty cycle of the PWM device. 0.0 is off, 1.0 is fully on. 43 | * Values in between may be specified for varying levels of power in the device. 44 | * 45 | * @param {float} [value] - When defined then sets the device duty cycle. 46 | * @returns {float} - When value is undefined then the current duty cycle is returned. 47 | */ 48 | PWMOutputDevice.prototype.value = function(value) { 49 | if (value === undefined) { 50 | return this._read(); 51 | } 52 | this._pin._stop_blink(); 53 | this._write(value); 54 | }; 55 | /** 56 | * Internal method that converts the actual pin value to it's logical value. 57 | * 58 | * @returns {number} - Logical pin value. 59 | * @private 60 | */ 61 | PWMOutputDevice.prototype._read = function() { 62 | this._check_open(); 63 | if (this.active_high()) { 64 | return this._pin.state(); 65 | } 66 | return 1 - this._pin.state(); 67 | }; 68 | 69 | /** 70 | * Internal method used to convert a logical value to the state the pin needs to change to. 71 | * 72 | * @param {float} value - Logical value to set the device to. 73 | * @private 74 | * @throws OutputDeviceBadValue - Occurs if the value specified is not between 0 and 1. 75 | */ 76 | PWMOutputDevice.prototype._write = function(value) { 77 | if (!this.active_high()) { 78 | value = 1 - value; 79 | } 80 | if (value < 0 || value > 1) { 81 | throw new exc.OutputDeviceBadValue("PWM value must be between 0 and 1"); 82 | } 83 | this._check_open(); 84 | this._pin.state(value); 85 | }; 86 | 87 | /** 88 | * Sets or Gets the device frequency. 89 | * 90 | * @param {int} [value] - The new frequency for the device. 91 | * @returns {int} - If value is undefined then the current device frequency is returned. 92 | */ 93 | PWMOutputDevice.prototype.frequency = function(value) { 94 | if (value === undefined) { 95 | return this._pin.frequency(); 96 | } 97 | this._pin.frequency(value); 98 | }; 99 | 100 | /** 101 | * 102 | * @returns {boolean} - If the device has a value other than 0 then true. 103 | */ 104 | PWMOutputDevice.prototype.is_active = function() { 105 | return this.value() !== 0; 106 | }; 107 | 108 | /** 109 | * Turn the device fully on. 110 | */ 111 | PWMOutputDevice.prototype.on = function() { 112 | this._pin._stop_blink(); 113 | this._write(1); 114 | }; 115 | 116 | /** 117 | * Turn the device off. 118 | */ 119 | PWMOutputDevice.prototype.off = function() { 120 | this._pin._stop_blink(); 121 | this._write(0); 122 | }; 123 | 124 | /** 125 | * Toggle the state of the device. If the device is currently off (value` is 0.0), 126 | * this changes it to "fully" on (`value` is 1.0). 127 | * If the device has a duty cycle (`value`) of 0.1, this will toggle it to 0.9, and so on. 128 | */ 129 | PWMOutputDevice.prototype.toggle = function() { 130 | this._pin._stop_blink(); 131 | const newValue = 1 - this.value(); 132 | this.value(newValue); 133 | }; 134 | 135 | /** 136 | * Stop any actions such as blink and unlink from pin. 137 | */ 138 | PWMOutputDevice.prototype.close = function() { 139 | this._pin._stop_blink(); 140 | this._pin.frequency(-1); 141 | OutputDevice.prototype.close.call(this); 142 | }; 143 | 144 | /** 145 | * Make the device turn on and off repeatedly. 146 | * 147 | * @param {float} [on_time] - Number of seconds on. Defaults to 1 second. 148 | * @param {float} [off_time] - Number of seconds off. Defaults to 1 second. 149 | * @param {float} [fade_in_time] - Number of seconds to spend fading in. Defaults to 0. 150 | * @param {float} [fade_out_time] - Number of seconds to spend fading out. Defaults to 0. 151 | * @param {int} [n] - Number of times to blink; ``undefined`` (the default) means forever. 152 | * @param {@callback} [callback] - Function to be called after n loops. 153 | */ 154 | PWMOutputDevice.prototype.blink = function(on_time, off_time, fade_in_time, fade_out_time, n, callback) { 155 | this._pin.blink(on_time, off_time, fade_in_time, fade_out_time, n, undefined, callback); 156 | }; 157 | 158 | /** 159 | * Make the device fade in and out repeatedly. 160 | * 161 | * @param {float} [fade_in_time] - Number of seconds to spend fading in. Defaults to 0. 162 | * @param {float} [fade_out_time] - Number of seconds to spend fading out. Defaults to 0. 163 | * @param {int} [n] - Number of times to blink; ``undefined`` (the default) means forever. 164 | * @param {@callback} [callback] - Function to be called after n loops. 165 | */ 166 | PWMOutputDevice.prototype.pulse = function(fade_in_time, fade_out_time, n, callback) { 167 | const on_time = 0, 168 | off_time = 0; 169 | 170 | this._pin.blink(on_time, off_time, fade_in_time, fade_out_time, n, undefined, callback); 171 | }; 172 | -------------------------------------------------------------------------------- /gpiozero/output_devices/RGBLED.js: -------------------------------------------------------------------------------- 1 | const Device = require('../devices/Device.js').Device; 2 | const exc = require('../exc.js'); 3 | const inherit = require('../tools.js').inherit; 4 | const PWMLED = require ('./PWMLED.js').PWMLED; 5 | const LED = require ('./LED.js').LED; 6 | 7 | exports.RGBLED = RGBLED; 8 | 9 | /** 10 | * 11 | * Represents a full color LED component (composed of red, green, and blue LEDs). 12 | * 13 | * Connect the common cathode (longest leg) to a ground pin; connect each of 14 | * the other legs (representing the red, green, and blue anodes) to any GPIO 15 | * pins. You can either use three limiting resistors (one per anode) or a 16 | * single limiting resistor on the cathode. 17 | * 18 | * @param {int} red - The GPIO pin that controls the red component of the RGB LED. 19 | * @param {int} green - The GPIO pin that controls the green component of the RGB LED. 20 | * @param {int} blue - The GPIO pin that controls the blue component of the RGB LED. 21 | * @param {boolean} [active_high] - Set to ``true`` (the default) for common cathode RGB LEDs. If you are 22 | * using a common anode RGB LED, set this to ``false``. 23 | * @param {Array} [initial_value] - The initial color for the RGB LED. Defaults to black ``[0, 0, 0]``. 24 | * @param {boolean} [pwm] - If ``true`` (the default), construct {@link PWMLED} instances for 25 | * each component of the RGBLED. If ``false``, construct regular {@link LED} instances, 26 | * which prevents smooth color graduations. 27 | * @class 28 | * @augments Device 29 | * @throws GPIOPinMissing - If one of the pins is not specified. 30 | */ 31 | function RGBLED(red, green, blue, active_high, initial_value, pwm) { 32 | this._leds = []; 33 | if (red === undefined || blue === undefined || green === undefined) { 34 | throw new exc.GPIOPinMissing('red, green, and blue pins must be provided'); 35 | } 36 | pwm = (pwm === undefined ? true : pwm); 37 | var LEDClass = pwm ? PWMLED : LED; 38 | Device.call(this); 39 | this._leds = [new LEDClass(red, active_high), new LEDClass(green, active_high), new LEDClass(blue, active_high)]; 40 | if (initial_value === undefined) { 41 | initial_value = [0, 0, 0]; 42 | } 43 | this.value(initial_value); 44 | } 45 | 46 | RGBLED.prototype = inherit(Device.prototype); 47 | RGBLED.prototype.constructor = RGBLED; 48 | 49 | /** 50 | * Represents the color of the LED as an RGB 3-tuple of ``[red, green, blue]`` 51 | * where each value is between 0 and 1 if ``pwm`` was ``true`` when the class was constructed 52 | * (and only 0 or 1 if not). 53 | * 54 | * @param {Array} [value] - If set, the value for each component will be updated. 55 | * @returns {Array} - If ``value`` is ``undefined`` then returns the current value for each component. 56 | * 57 | * @throws OutputDeviceBadValue - If three values are not passed as an array in value. 58 | * @throws OutputDeviceBadValue - If any of the RGB values are not between 0 and 1. 59 | * @throws OutputDeviceBadValue - If pwm is false but a value is between 0 and 1. 60 | */ 61 | RGBLED.prototype.value = function(value) { 62 | if (value === undefined) { 63 | return [this.red, this.green, this.blue]; 64 | } 65 | if (value.length < 3) { 66 | throw new exc.OutputDeviceBadValue('RGB values must be an array of three components'); 67 | } 68 | var i; 69 | for (i = 0; i < 3; i++) { 70 | if (value[i] < 0 || value[i] > 1) { 71 | throw new exc.OutputDeviceBadValue('each RGB component must be between 0 and 1'); 72 | } 73 | if (this._leds[i] instanceof LED) { 74 | if (value[i] !== 0 && value[i] !== 1) { 75 | throw new exc.OutputDeviceBadValue('each RGB color component must be 0 or 1 with non-PWM RGBLEDs'); 76 | } 77 | } 78 | } 79 | 80 | for (i = 0; i < 3; i++) { 81 | this._leds[i].value(value[i]); 82 | } 83 | this.red = this._leds[0].value(); 84 | this.green = this._leds[1].value(); 85 | this.blue = this._leds[2].value(); 86 | }; 87 | 88 | /** 89 | * Close each pin and release for reuse. 90 | */ 91 | RGBLED.prototype.close = function() { 92 | var i; 93 | for (i = 0; i < 3; i++) { 94 | if (this._leds[i] !== undefined) { 95 | this._leds[i].close(); 96 | this._leds[i] = undefined; 97 | } 98 | } 99 | this._leds = []; 100 | Device.prototype.close.call(this); 101 | }; 102 | 103 | /** 104 | * 105 | * @returns {boolean} - If the LED is currently active (not black) then ``true`` otherwise ``false``. 106 | */ 107 | RGBLED.prototype.is_active = function() { 108 | return (this.value()[0] + this.value()[1] + this.value()[2] > 0); 109 | }; 110 | 111 | /** 112 | * Turn the LED on. This equivalent to setting the LED color to white ``[1, 1, 1]``. 113 | */ 114 | RGBLED.prototype.on = function() { 115 | this.value([1, 1, 1]); 116 | }; 117 | 118 | /** 119 | * Turn the LED off. This equivalent to setting the LED color to black ``[0, 0, 0]``. 120 | */ 121 | RGBLED.prototype.off = function() { 122 | this.value([0, 0, 0]); 123 | }; 124 | 125 | /** 126 | * Toggle the state of the device. If the device is currently off (`value` is ``[0, 0, 0[``), 127 | * this changes it to "fully" on (`value` is ``[1, 1, 1]``). 128 | * If the device has a specific color, this method inverts the color. 129 | */ 130 | RGBLED.prototype.toggle = function() { 131 | var current = this.value(); 132 | this.value([1 - current[0], 1 - current[1], 1 - current[2]]); 133 | }; 134 | 135 | RGBLED.prototype.closed = function() { 136 | return this._leds.length === 0; 137 | }; 138 | 139 | /*RGBLED.prototype.blink = function(on_time, off_time, fade_in_time, fade_out_time, on_color, off_color, n, callback) { 140 | 141 | /* 142 | Make the device turn on and off repeatedly. 143 | 144 | :param float on_time: 145 | Number of seconds on. Defaults to 1 second. 146 | 147 | :param float off_time: 148 | Number of seconds off. Defaults to 1 second. 149 | 150 | :param float fade_in_time: 151 | Number of seconds to spend fading in. Defaults to 0. 152 | 153 | :param float fade_out_time: 154 | Number of seconds to spend fading out. Defaults to 0. 155 | 156 | :param tuple on_color: 157 | The color to use when the LED is "on". Defaults to white. 158 | 159 | :param tuple off_color: 160 | The color to use when the LED is "off". Defaults to black. 161 | 162 | :param int n: 163 | Number of times to blink; ``None`` (the default) means forever. 164 | 165 | 166 | if (this._leds[0] instanceof LED) { 167 | if (fade_in_time !== undefined) { 168 | throw new exc.ValueError('fade_in_time must be 0 with non-PWM RGBLEDs'); 169 | } 170 | if (fade_out_time !== undefined) { 171 | throw new exc.ValueError('fade_out_time must be 0 with non-PWM RGBLEDs'); 172 | } 173 | } 174 | 175 | this._leds[0].blink (on_time, off_time, fade_in_time, fade_out_time, n, callback); 176 | this._leds[1].blink (on_time, off_time, fade_in_time, fade_out_time, n, callback); 177 | this._leds[2].blink (on_time, off_time, fade_in_time, fade_out_time, n, callback); 178 | 179 | }; 180 | 181 | RGBLED.prototype._stop_blink = function () { 182 | this._leds[0]._pin._stop_blink(); 183 | this._leds[1]._pin._stop_blink(); 184 | this._leds[2]._pin._stop_blink(); 185 | } 186 | 187 | /* def _blink_device( 188 | self, on_time, off_time, fade_in_time, fade_out_time, on_color, 189 | off_color, n, fps=25): 190 | # Define some simple lambdas to perform linear interpolation between 191 | # off_color and on_color 192 | lerp = lambda t, fade_in: tuple( 193 | (1 - t) * off + t * on 194 | if fade_in else 195 | (1 - t) * on + t * off 196 | for off, on in zip(off_color, on_color) 197 | ) 198 | sequence = [] 199 | if fade_in_time > 0: 200 | sequence += [ 201 | (lerp(i * (1 / fps) / fade_in_time, True), 1 / fps) 202 | for i in range(int(fps * fade_in_time)) 203 | ] 204 | sequence.append((on_color, on_time)) 205 | if fade_out_time > 0: 206 | sequence += [ 207 | (lerp(i * (1 / fps) / fade_out_time, False), 1 / fps) 208 | for i in range(int(fps * fade_out_time)) 209 | ] 210 | sequence.append((off_color, off_time)) 211 | sequence = ( 212 | cycle(sequence) if n is None else 213 | chain.from_iterable(repeat(sequence, n)) 214 | ) 215 | for l in self._leds: 216 | l._controller = self 217 | for value, delay in sequence: 218 | for l, v in zip(self._leds, value): 219 | l._write(v) 220 | if self._blink_thread.stopping.wait(delay): 221 | break 222 | */ 223 | 224 | 225 | /* 226 | class RGBLED(SourceMixin, Device): 227 | 228 | 229 | def blink( 230 | self, on_time=1, off_time=1, fade_in_time=0, fade_out_time=0, 231 | on_color=(1, 1, 1), off_color=(0, 0, 0), n=None, background=True): 232 | """ 233 | Make the device turn on and off repeatedly. 234 | 235 | :param float on_time: 236 | Number of seconds on. Defaults to 1 second. 237 | 238 | :param float off_time: 239 | Number of seconds off. Defaults to 1 second. 240 | 241 | :param float fade_in_time: 242 | Number of seconds to spend fading in. Defaults to 0. Must be 0 if 243 | ``pwm`` was ``False`` when the class was constructed 244 | (:exc:`ValueError` will be raised if not). 245 | 246 | :param float fade_out_time: 247 | Number of seconds to spend fading out. Defaults to 0. Must be 0 if 248 | ``pwm`` was ``False`` when the class was constructed 249 | (:exc:`ValueError` will be raised if not). 250 | 251 | :param tuple on_color: 252 | The color to use when the LED is "on". Defaults to white. 253 | 254 | :param tuple off_color: 255 | The color to use when the LED is "off". Defaults to black. 256 | 257 | :param int n: 258 | Number of times to blink; ``None`` (the default) means forever. 259 | 260 | :param bool background: 261 | If ``True`` (the default), start a background thread to continue 262 | blinking and return immediately. If ``False``, only return when the 263 | blink is finished (warning: the default value of *n* will result in 264 | this method never returning). 265 | """ 266 | if isinstance(self._leds[0], LED): 267 | if fade_in_time: 268 | raise ValueError('fade_in_time must be 0 with non-PWM RGBLEDs') 269 | if fade_out_time: 270 | raise ValueError('fade_out_time must be 0 with non-PWM RGBLEDs') 271 | 272 | def pulse( 273 | self, fade_in_time=1, fade_out_time=1, 274 | on_color=(1, 1, 1), off_color=(0, 0, 0), n=None, background=True): 275 | """ 276 | Make the device fade in and out repeatedly. 277 | 278 | :param float fade_in_time: 279 | Number of seconds to spend fading in. Defaults to 1. 280 | 281 | :param float fade_out_time: 282 | Number of seconds to spend fading out. Defaults to 1. 283 | 284 | :param tuple on_color: 285 | The color to use when the LED is "on". Defaults to white. 286 | 287 | :param tuple off_color: 288 | The color to use when the LED is "off". Defaults to black. 289 | 290 | :param int n: 291 | Number of times to pulse; ``None`` (the default) means forever. 292 | 293 | :param bool background: 294 | If ``True`` (the default), start a background thread to continue 295 | pulsing and return immediately. If ``False``, only return when the 296 | pulse is finished (warning: the default value of *n* will result in 297 | this method never returning). 298 | """ 299 | on_time = off_time = 0 300 | self.blink( 301 | on_time, off_time, fade_in_time, fade_out_time, 302 | on_color, off_color, n, background 303 | ) 304 | 305 | def _stop_blink(self, led=None): 306 | # If this is called with a single led, we stop all blinking anyway 307 | if self._blink_thread: 308 | self._blink_thread.stop() 309 | self._blink_thread = None 310 | 311 | 312 | 313 | 314 | */ -------------------------------------------------------------------------------- /gpiozero/pins/wiringpi.js: -------------------------------------------------------------------------------- 1 | const wpi = require("wiring-pi"); 2 | const p = require("./index.js"); 3 | const exc = require("../exc.js"); 4 | const inherit = require('../tools.js').inherit; 5 | const Pin = require("./index.js").Pin; 6 | 7 | var _PINS = {}, 8 | WIRING_PI, 9 | PI_INFO, 10 | GPIO_FUNCTIONS = { 11 | 'input': wpi.INPUT, 12 | 'output': wpi.OUTPUT, 13 | //'i2c': GPIO.I2C, 14 | //'spi': GPIO.SPI, 15 | 'pwm': wpi.PWM_OUTPUT, 16 | //'serial': GPIO.SERIAL, 17 | //'unknown': GPIO.UNKNOWN, 18 | }, 19 | GPIO_PULL_UPS = { 20 | 'up': wpi.PUD_UP, 21 | 'down': wpi.PUD_DOWN, 22 | 'floating': wpi.PUD_OFF, 23 | }; 24 | 25 | exports.WiringPiPin = WiringPiPin; 26 | 27 | function WiringPiPin(number) { 28 | /* 29 | Uses the `wiringPi`_ library to interface to the Pi's GPIO pins. This is 30 | the default pin implementation. 31 | Supports all features including PWM (via software). 32 | 33 | Because this is the default pin implementation you can use it simply by 34 | specifying an integer number for the pin in most operations, e.g.:: 35 | 36 | from gpiozero import LED 37 | 38 | led = LED(12) 39 | 40 | However, you can also construct RPi.GPIO pins manually if you wish:: 41 | 42 | from gpiozero.pins.rpigpio import RPiGPIOPin 43 | from gpiozero import LED 44 | 45 | led = LED(RPiGPIOPin(12)) 46 | 47 | 48 | */ 49 | if (WIRING_PI === undefined) { 50 | wpi.setup('gpio'); 51 | WIRING_PI = true; 52 | } 53 | /* 54 | 55 | GPIO_EDGES = { 56 | 'both': GPIO.BOTH, 57 | 'rising': GPIO.RISING, 58 | 'falling': GPIO.FALLING, 59 | } 60 | 61 | GPIO_FUNCTION_NAMES = {v: k for (k, v) in GPIO_FUNCTIONS.items()} 62 | GPIO_PULL_UP_NAMES = {v: k for (k, v) in GPIO_PULL_UPS.items()} 63 | GPIO_EDGES_NAMES = {v: k for (k, v) in GPIO_EDGES.items()} 64 | */ 65 | 66 | 67 | 68 | if (PI_INFO === undefined) { 69 | PI_INFO = wpi.piBoardRev(); 70 | } 71 | if (number < 0 || number > 54) { 72 | throw new Error('invalid pin ' + number.toString() + ' specified (must be 0..53)'); 73 | } 74 | 75 | if (_PINS[number] !== undefined) { 76 | return _PINS[number]; 77 | } 78 | p.Pin.call(this); 79 | this._number = number; 80 | this._pwm = undefined; 81 | this._frequency = undefined; 82 | this._duty_cycle = undefined; 83 | this._bounce = -666; 84 | this._when_changed = undefined; 85 | this._function = 'input'; 86 | this._state = false; 87 | this._pull = 'floating'; 88 | this._bounce = undefined; 89 | this._edges = 'both'; 90 | 91 | wpi.pinMode(number, wpi.INPUT); 92 | _PINS[number] = this; 93 | return this; 94 | } 95 | 96 | WiringPiPin.prototype = inherit(p.LocalPin.prototype); 97 | WiringPiPin.prototype.constructor = WiringPiPin; 98 | 99 | WiringPiPin.prototype.toString = function() { 100 | return "GPIO " + this._number.toString(); 101 | }; 102 | WiringPiPin.prototype.when_changed = function(next) { 103 | this._when_changed = next; 104 | } 105 | 106 | WiringPiPin.prototype.number = function() { 107 | return this._number(); 108 | }; 109 | 110 | WiringPiPin.prototype.close = function() { 111 | this._frequency = undefined; 112 | this._when_changed = undefined; 113 | wpi.pullUpDnControl(this._number, wpi.PUD_OFF); 114 | }; 115 | 116 | WiringPiPin.prototype.output_with_state = function(state) { 117 | this._pull = 'floating'; 118 | this.pin_function ('output'); 119 | wpi.digitalWrite(this._number, state); 120 | }; 121 | 122 | WiringPiPin.prototype.input_with_pull = function(pull) { 123 | // if (pull != 'up' and self.PI_INFO.pulled_up('GPIO%d' % self._number): 124 | // raise PinFixedPull('%r has a physical pull-up resistor' % self) 125 | //try: 126 | wpi.pinMode(this._number, wpi.IN); 127 | //GPIO.setup(self._number, GPIO.IN, self.GPIO_PULL_UPS[pull]) 128 | wpi.pullUpDnControl(this._number, wpi.PUD_UP); 129 | this._pull = pull; 130 | //except KeyError: 131 | // raise PinInvalidPull('invalid pull "%s" for pin %r' % (pull, self)) 132 | }; 133 | 134 | WiringPiPin.prototype.pin_function = function(value) { 135 | if (value === undefined) { 136 | return this._function; 137 | } 138 | if (value !== 'input') { 139 | this._pull = 'floating'; 140 | } 141 | if (value === 'input' || value === 'output') { 142 | wpi.pinMode(this._number, GPIO_FUNCTIONS[value]); 143 | wpi.pullUpDnControl(this._number, GPIO_PULL_UPS[this._pull]); 144 | this._function = value; 145 | } else { 146 | throw exc.PinInvalidFunction('invalid function " + value + " for pin ' + this._number.toString()); 147 | } 148 | }; 149 | 150 | WiringPiPin.prototype.state = function(value) { 151 | if (value === undefined) { 152 | if (this._pwm !== undefined) { 153 | return this._duty_cycle; 154 | } 155 | return wpi.digitalRead(this._number); 156 | } 157 | if (this._pwm !== undefined) { 158 | wpi.pwmWrite(this._number, value); 159 | this._duty_cycle = value; 160 | } else { 161 | wpi.digitalWrite(this._number, value ? 1 : 0); 162 | } 163 | }; 164 | 165 | WiringPiPin.prototype.pull = function(value) { 166 | if (value === undefined) { 167 | return this._pull; 168 | } 169 | if (this.function !== 'input') { 170 | throw new exc.PinFixedPull('cannot set pull on non-input pin ' + this._number.toString()); 171 | } 172 | /*if value != 'up' and self.PI_INFO.pulled_up('GPIO%d' % self._number): 173 | raise PinFixedPull('%r has a physical pull-up resistor' % self) 174 | }*/ 175 | this._pull = value; 176 | wpi.pullUpDnControl(this._number, this.GPIO_PULL_UPS[this._pull]); 177 | }; 178 | 179 | WiringPiPin.prototype.frequency = function(value) { 180 | if (value === undefined) { 181 | return this._frequency; 182 | } 183 | if (this._function !== 'output') { 184 | throw new exc.PinSetInput("Pin is not set for output function"); 185 | } 186 | if (value === -1) { 187 | this._frequency = undefined; 188 | this._pwm = undefined; 189 | wpi.pwmToneWrite(this._number, 0); 190 | } else { 191 | if (this._frequency === undefined) { 192 | this._pwm = wpi.pinMode(this._number, wpi.PWM_OUTPUT); 193 | } 194 | wpi.pwmToneWrite(this._number, value); 195 | this._frequency = value; 196 | } 197 | }; 198 | 199 | WiringPiPin.prototype.blink = function(on_time, off_time, fade_in_time, fade_out_time, n, fps, callback) { 200 | 201 | if(this._pwm === undefined) { 202 | Pin.prototype.blink.call(this, on_time, off_time, n, callback); 203 | return; 204 | } 205 | this.on_time = (on_time === undefined ? 1 : on_time); 206 | this.off_time = (off_time === undefined ? 1 : off_time); 207 | this.fade_in_time = (fade_in_time === undefined ? 0 : fade_in_time); 208 | this.fade_out_time = (fade_out_time === undefined ? 0 : fade_out_time); 209 | this.fps = (fps === undefined ? 50 : fps); 210 | this.n = (n === undefined ? 0 : n); 211 | this.sequence = []; 212 | this.blink_callback = callback; 213 | var i = 0; 214 | 215 | if (this.fade_in_time > 0) { 216 | for (i = 0; i < this.fps * this.fade_in_time; i++) { 217 | this.sequence.push({ 218 | value: i * (1 / this.fps) / this.fade_in_time, 219 | delay: 1 / this.fps 220 | }); 221 | } 222 | } 223 | this.sequence.push({ 224 | value: 1, 225 | delay: this.on_time 226 | }); 227 | 228 | if (this.fade_out_time > 0) { 229 | for (i = 0; i < this.fps * this.fade_out_time; i++) { 230 | this.sequence.push({ 231 | value: 1 - (i * (1 / this.fps)) / this.fade_out_time, 232 | delay: 1 / this.fps 233 | }); 234 | } 235 | } 236 | this.sequence.push({ 237 | value: 0, 238 | delay: this.off_time 239 | }); 240 | 241 | if (this.n > 0) { 242 | for (i = 0; i < (this.n - 1); i++) { 243 | this.sequence = this.sequence.concat(this.sequence); 244 | } 245 | 246 | var nextStep = this.sequence.pop(); 247 | this.state(nextStep.value); 248 | var that = this; 249 | this._blink_timer = setTimeout(that._run_blink, nextStep.delay, this.sequence, this); 250 | } 251 | }; 252 | 253 | WiringPiPin.prototype._run_blink = function(sequence, that) { 254 | if (sequence.length > 0) { 255 | var nextStep = sequence.pop(); 256 | that.state(nextStep.value); 257 | that._blink_timer = setTimeout(that._run_blink, nextStep.delay, sequence, that); 258 | } else if (that.blink_callback !== undefined) { 259 | that.blink_callback(); 260 | } 261 | }; 262 | 263 | /* 264 | 265 | def _get_bounce(self): 266 | return None if self._bounce == -666 else (self._bounce / 1000) 267 | 268 | def _set_bounce(self, value): 269 | if value is not None and value < 0: 270 | raise PinInvalidBounce('bounce must be 0 or greater') 271 | f = self.when_changed 272 | self.when_changed = None 273 | try: 274 | self._bounce = -666 if value is None else int(value * 1000) 275 | finally: 276 | self.when_changed = f 277 | 278 | def _get_edges(self): 279 | return self.GPIO_EDGES_NAMES[self._edges] 280 | 281 | def _set_edges(self, value): 282 | f = self.when_changed 283 | self.when_changed = None 284 | try: 285 | self._edges = self.GPIO_EDGES[value] 286 | finally: 287 | self.when_changed = f 288 | 289 | def _get_when_changed(self): 290 | return self._when_changed 291 | 292 | def _set_when_changed(self, value): 293 | if self._when_changed is None and value is not None: 294 | self._when_changed = value 295 | GPIO.add_event_detect( 296 | self._number, self._edges, 297 | callback=lambda channel: self._when_changed(), 298 | bouncetime=self._bounce) 299 | elif self._when_changed is not None and value is None: 300 | GPIO.remove_event_detect(self._number) 301 | self._when_changed = None 302 | else: 303 | self._when_changed = value 304 | 305 | */ -------------------------------------------------------------------------------- /gpiozero/tools.js: -------------------------------------------------------------------------------- 1 | exports.with_close = function(device, method) { 2 | method(device); 3 | device.close(); 4 | }; 5 | 6 | 7 | exports.inherit = function(proto) { 8 | /*eslint no-empty-function: off*/ 9 | function F() {} 10 | F.prototype = proto; 11 | return new F(); 12 | }; 13 | 14 | // Pass in the objects to merge as arguments. 15 | // For a deep extend, set the first argument to `true`. 16 | exports.extend = extend; 17 | 18 | /*eslint prefer-rest-params: off*/ 19 | function extend() { 20 | 21 | // Variables 22 | const extended = {}; 23 | let deep = false; 24 | let i = 0; 25 | const length = arguments.length; 26 | 27 | // Check if a deep merge 28 | if (Object.prototype.toString.call(arguments[0]) === '[object Boolean]') { 29 | deep = arguments[0]; 30 | i++; 31 | } 32 | 33 | // Merge the object into the extended object 34 | const merge = function(obj) { 35 | for (const prop in obj) { 36 | if (Object.prototype.hasOwnProperty.call(obj, prop)) { 37 | // If deep merge and property is an object, merge properties 38 | if (deep && Object.prototype.toString.call(obj[prop]) === '[object Object]') { 39 | extended[prop] = extend(true, extended[prop], obj[prop]); 40 | } else { 41 | extended[prop] = obj[prop]; 42 | } 43 | } 44 | } 45 | }; 46 | 47 | // Loop through each object and conduct a merge 48 | for (; i < length; i++) { 49 | const obj = arguments[i]; 50 | merge(obj); 51 | } 52 | 53 | return extended; 54 | } 55 | 56 | /*eslint prefer-rest-params: off*/ 57 | function _extend_object() { 58 | 59 | // Variables 60 | 61 | let deep = false; 62 | let i = 0; 63 | const length = arguments.length; 64 | 65 | // Check if a deep merge 66 | if (Object.prototype.toString.call(arguments[0]) === '[object Boolean]') { 67 | deep = arguments[0]; 68 | i++; 69 | } 70 | const extended = arguments[i]; 71 | i++; 72 | 73 | // Merge the object into the extended object 74 | const merge = function(obj) { 75 | for (const prop in obj) { 76 | if (Object.prototype.hasOwnProperty.call(obj, prop)) { 77 | // If deep merge and property is an object, merge properties 78 | if (deep && Object.prototype.toString.call(obj[prop]) === '[object Object]') { 79 | extended[prop] = extend(true, extended[prop], obj[prop]); 80 | } else { 81 | extended[prop] = obj[prop]; 82 | } 83 | } 84 | } 85 | }; 86 | // Loop through each object and conduct a merge 87 | for (; i < length; i++) { 88 | const obj = arguments[i]; 89 | merge(obj); 90 | } 91 | } 92 | 93 | // Pass in the objects to merge as arguments. 94 | // For a deep extend, set the first argument to `true`. 95 | exports._extend_object = _extend_object; -------------------------------------------------------------------------------- /jsdoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "opts": { 3 | "template": "node_modules/docdash/", 4 | "encoding": "utf8", 5 | "destination": "docs/", 6 | "recurse": true, 7 | "verbose": true 8 | }, 9 | "templates": { 10 | "cleverLinks": false, 11 | "monospaceLinks": false 12 | } 13 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0", 3 | "name": "js-gpiozero", 4 | "description": "A simple interface to GPIO devices with Raspberry Pi using nodejs", 5 | "main": "./gpiozero/index.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/miketrebilcock/js-gpiozero.git" 9 | }, 10 | "bugs": { 11 | "url": "https://github.com/miketrebilcock/js-gpiozero/issues" 12 | }, 13 | "scripts": { 14 | "test": "istanbul cover node_modules/mocha/bin/_mocha && codecov", 15 | "changelog": "standard-changelog -i CHANGELOG.md -w", 16 | "lint": "eslint ./gpiozero/**/*.js ./test/**/*.js", 17 | "docs": "jsdoc ./gpiozero -R ./README.md -d docs -c jsdoc.json", 18 | "semantic-release": "semantic-release pre && npm publish && semantic-release post" 19 | }, 20 | "dependencies": { 21 | "rwlock": "5.0.0", 22 | "wiring-pi": "^2.2.1" 23 | }, 24 | "devDependencies": { 25 | "chai": "3.5.0", 26 | "codecov": "3.6.5", 27 | "cz-conventional-changelog": "1.2.0", 28 | "docdash": "0.4.0", 29 | "eslint": "3.19.0", 30 | "eslint-config-airbnb-base": "11.3.2", 31 | "eslint-config-node": "1.6.0", 32 | "eslint-plugin-import": "2.20.2", 33 | "eslint-plugin-jsdoc": "2.4.0", 34 | "istanbul": "0.4.5", 35 | "jsdoc": "3.6.4", 36 | "mocha": "3.5.3", 37 | "mocha-eslint": "3.0.1", 38 | "semantic-release": "6.3.6" 39 | }, 40 | "keywords": [ 41 | "wiringPi", 42 | "gpio", 43 | "raspberry", 44 | "pi", 45 | "raspberrypi", 46 | "bcm2835" 47 | ], 48 | "author": "Mike Trebilcock ", 49 | "contributors": [], 50 | "license": "ISC", 51 | "homepage": "https://miketrebilcock.github.io/js-gpiozero/", 52 | "directories": { 53 | "doc": "docs", 54 | "test": "tests" 55 | }, 56 | "config": { 57 | "commitizen": { 58 | "path": "./node_modules/cz-conventional-changelog" 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /pre-commit.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # We only want to test the commited files 3 | # so get rid of everything else 4 | git stash -q --keep-index 5 | 6 | npm test 7 | RESULT=$? 8 | 9 | npm run docs 10 | git add ./docs/** 11 | 12 | ## Restore the stashed files so the directory 13 | ## is as it was at the start 14 | git stash pop -q 15 | 16 | [ $RESULT -ne 0 ] && exit 1 17 | exit 0 -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /test/devices.spec.js: -------------------------------------------------------------------------------- 1 | /*global it describe afterEach */ 2 | 3 | const expect = require('chai').expect; 4 | const assert = require('chai').assert; 5 | const gz = require('../gpiozero/'); 6 | const mp = require('../gpiozero/pins/mock.js'); 7 | const with_close = require('../gpiozero/').with_close; 8 | 9 | describe('devices', () => { 10 | 11 | afterEach(() => { 12 | mp.clear_pins(); 13 | }); 14 | 15 | it('no_pin_throws_error', () => { 16 | expect(() => { 17 | /*eslint no-new: off*/ 18 | new gz.GPIODevice(); 19 | }).to.throw(gz.GPIOPinMissing); 20 | }); 21 | 22 | it('device_init', () => { 23 | var pin = new mp.MockPin(1); 24 | with_close(new gz.GPIODevice(pin), (device) => { 25 | assert(device.closed() === false, "Device is incorrectly reporting closed"); 26 | assert(device.pin() === pin, "Device has not returned correct pin"); 27 | }); 28 | }); 29 | 30 | it('device_init_twice_on_same_pin_fails', () => { 31 | var pin = new mp.MockPin(1); 32 | with_close(new gz.GPIODevice(pin), () => { 33 | expect(() => { 34 | /*eslint no-new: off*/ 35 | new gz.GPIODevice(pin); 36 | }).to.throw(gz.GPIOPinInUse); 37 | }); 38 | }); 39 | 40 | it('device_init_twice_on_diffent_pins_suceeds', () => { 41 | var pin = new mp.MockPin(1), 42 | pin2 = new mp.MockPin(2); 43 | with_close(new gz.GPIODevice(pin), (device1) => { 44 | with_close(new gz.GPIODevice(pin2), (device2) => { 45 | assert(device1.pin() === pin, "Device has not returned correct pin"); 46 | assert(device2.pin() === pin2, "Device has not returned correct pin"); 47 | }); 48 | }); 49 | }); 50 | 51 | it('device_close', () => { 52 | var pin = new mp.MockPin(1), 53 | device = new gz.GPIODevice(pin); 54 | device.close(); 55 | assert(device.closed() === true, "Device is incorrectly reporting open"); 56 | assert(device.pin() === undefined, "Device still holding onto pin"); 57 | }); 58 | 59 | it('reopen_same_pin', () => { 60 | var pin = new mp.MockPin(1), 61 | device = new gz.GPIODevice(pin); 62 | device.close(); 63 | var device2 = new gz.GPIODevice(pin); 64 | assert(device2.closed() === false, "Device is incorrectly reporting closed"); 65 | assert(device2.pin() === pin, "Device has not returned correct pin"); 66 | assert(device.closed() === true, "Device is incorrectly reporting open"); 67 | assert(device.pin() === undefined, "Device still holding onto pin"); 68 | device2.close(); 69 | }); 70 | 71 | it('device_toString', () => { 72 | var pin = new mp.MockPin(1); 73 | with_close(new gz.GPIODevice(pin), (device) => { 74 | expect(device.toString()).to.equal(""); 75 | }); 76 | }); 77 | 78 | it('compsite_device_sequence', () => { 79 | with_close(new gz.CompositeDevice([new gz.OutputDevice(new mp.MockPin(2)), 80 | new gz.OutputDevice(new mp.MockPin(3))]), 81 | (device) => { 82 | assert(device.length() === 2, "CompositeDevice length is not 2"); 83 | assert(device[0]._pin.number() === 2); 84 | assert(device[1]._pin.number() === 3); 85 | assert(device.namedtuple()[0] === '_0', "CompositeDevice NamedTuple returned "+device.namedtuple()); 86 | assert(device.namedtuple()[1] === '_1', "CompositeDevice NamedTuple returned "+device.namedtuple()); 87 | }); 88 | }); 89 | 90 | it('compsite_device_values', () => { 91 | with_close(new gz.CompositeDevice([new gz.OutputDevice(new mp.MockPin(2)), 92 | new gz.OutputDevice(new mp.MockPin(3))]), 93 | (device) => { 94 | assert(device.value()[0] === false, "CompositeDevice value[0] is not false"); 95 | assert(device.value()[1] === false, "CompositeDevice value[1] is not false"); 96 | assert(device.is_active() === false, "CompositeDevice is_active is not false"); 97 | device[0]._pin.state(true); 98 | assert(true === device.value()[0], "CompositeDevice value[0] is not true"); 99 | assert(false === device.value()[1], "CompositeDevice value[1] is not false"); 100 | assert(true === device.is_active(), "CompositeDevice is_active is not true"); 101 | }); 102 | }); 103 | 104 | it('compsite_device_named', () => { 105 | with_close(new gz.CompositeDevice(undefined,[ 106 | ['foo', new gz.OutputDevice(new mp.MockPin(2))], 107 | ['bar', new gz.OutputDevice(new mp.MockPin(3))] 108 | ]), 109 | (device) => { 110 | assert(device.namedtuple()[0] === 'foo', "CompositeDevice NamedTuple returned "+device.namedtuple()); 111 | assert(device.namedtuple()[1] === 'bar', "CompositeDevice NamedTuple returned "+device.namedtuple()); 112 | assert(device.value()[0] === false, "CompositeDevice value[0] is not false"); 113 | assert(device.value()[1] === false, "CompositeDevice value[1] is not false"); 114 | assert(device.is_active() === false, "CompositeDevice is_active is not false"); 115 | assert(device.foo.value() === false, "CompositeDevice value[0] is not false"); 116 | assert(device.bar.value() === false, "CompositeDevice value[1] is not false"); 117 | device.foo._pin.state(true); 118 | assert(device.foo.value() === true, "CompositeDevice value[0] is not true"); 119 | }); 120 | }); 121 | 122 | /* 123 | 124 | def test_composite_device_bad_init(): 125 | with pytest.raises(ValueError): 126 | CompositeDevice(foo=1, bar=2, _order=('foo',)) 127 | with pytest.raises(ValueError): 128 | CompositeDevice(close=1) 129 | with pytest.raises(ValueError): 130 | CompositeDevice(2) 131 | with pytest.raises(ValueError): 132 | CompositeDevice(MockPin(2)) 133 | 134 | def test_composite_device_read_only(): 135 | device = CompositeDevice( 136 | foo=InputDevice(MockPin(2)), 137 | bar=InputDevice(MockPin(3)) 138 | ) 139 | with pytest.raises(AttributeError): 140 | device.foo = 1 141 | 142 | */ 143 | 144 | }); 145 | 146 | /* 147 | def test_device_repr(): 148 | pin = MockPin(2) 149 | with GPIODevice(pin) as device: 150 | assert repr(device) == '' % pin 151 | 152 | def test_device_repr_after_close(): 153 | pin = MockPin(2) 154 | device = GPIODevice(pin) 155 | device.close() 156 | assert repr(device) == '' 157 | 158 | 159 | */ -------------------------------------------------------------------------------- /test/eslint.spec.js: -------------------------------------------------------------------------------- 1 | const lint = require('mocha-eslint'); 2 | 3 | // Array of paths to lint 4 | // Note: a seperate Mocha test will be run for each path and each file which 5 | // matches a glob pattern 6 | const paths = [ 7 | 'gpiozero/**/*.js', 8 | 'test/**/*spec.js', 9 | ]; 10 | 11 | var options = { 12 | // Specify style of output 13 | //formatter: 'compact', // Defaults to `stylish` 14 | 15 | // Only display warnings if a test is failing 16 | //alwaysWarn: false, // Defaults to `true`, always show warnings 17 | 18 | // Increase the timeout of the test if linting takes to long 19 | //timeout: 5000, // Defaults to the global mocha `timeout` option 20 | 21 | // Increase the time until a test is marked as slow 22 | //slow: 1000, // Defaults to the global mocha `slow` option 23 | 24 | // Consider linting warnings as errors and return failure 25 | strict: true // Defaults to `false`, only notify the warnings 26 | }; 27 | 28 | // Run the tests 29 | lint(paths, options); -------------------------------------------------------------------------------- /test/input_devices.spec.js: -------------------------------------------------------------------------------- 1 | /*global it describe afterEach context */ 2 | const expect = require('chai').expect; 3 | const assert = require('chai').assert; 4 | const gz = require('../gpiozero/index.js'); 5 | const mp = require('../gpiozero/pins/mock.js'); 6 | const with_close = require ('../gpiozero/tools.js').with_close; 7 | 8 | describe('input_devices', () => { 9 | 10 | afterEach(() => { 11 | mp.clear_pins(); 12 | }); 13 | context('input_device', ()=> { 14 | it('initial_values', () => { 15 | const pin = new mp.MockPin(2); 16 | with_close(new gz.InputDevice(pin, true), (device) => { 17 | assert(pin.pin_function() === 'input', 'Input pin function is not set to input'); 18 | assert(pin.pull() === 'up', 'Input pin is not set to pull up'); 19 | assert(device.pull_up(), 'Device pull_up is not true'); 20 | device.close(); 21 | device = new gz.InputDevice(pin); 22 | assert(pin.pull() === 'down', 'Input pin is not set to pull down'); 23 | assert(device.pull_up() === false, 'Device pull_up is not false'); 24 | }); 25 | }); 26 | 27 | it('is_active_low', () => { 28 | const pin = new mp.MockPin(2); 29 | with_close(new gz.InputDevice(pin, true), (device) => { 30 | pin.drive_high(); 31 | assert(device.is_active() === false, 'Device should not be active'); 32 | assert(device.toString() === '', 'ToString is incorrect:'+device.toString()); 33 | pin.drive_low(); 34 | assert(device.is_active() === true, 'Device should be active'); 35 | assert(device.toString() === '', 'ToString is incorrect:'+device.toString()); 36 | }); 37 | }); 38 | 39 | it('is_active_high', () => { 40 | const pin = new mp.MockPin(2); 41 | with_close(new gz.InputDevice(pin), (device) => { 42 | pin.drive_high(); 43 | assert(device.is_active() === true, 'Device should be active'); 44 | assert(device.toString() === '', 'ToString is incorrect:'+device.toString()); 45 | pin.drive_low(); 46 | assert(device.is_active() === false, 'Device should not be active'); 47 | assert(device.toString() === '', 'ToString is incorrect:'+device.toString()); 48 | }); 49 | }); 50 | 51 | it('is pulled up', () => { 52 | const pin = new mp.MockPulledUpPin(2); 53 | expect(() => { 54 | /*eslint no-new: off*/ 55 | new gz.InputDevice(pin, true); 56 | }).to.throw(gz.PinFixedPull); 57 | }); 58 | }); 59 | context('digital_input_device', ()=> { 60 | it('is event activated', () => { 61 | let event = false; 62 | const pin = new mp.MockPin(2); 63 | with_close(new gz.DigitalInputDevice(pin), (device) => { 64 | device.when_activated = function (){ 65 | event = true; 66 | }; 67 | assert (event === false, "Event is not set to false"); 68 | pin.drive_high(); 69 | assert (event === true, "Event is not set to true"); 70 | }); 71 | }); 72 | it('is event activated', () => { 73 | let event = false; 74 | const pin = new mp.MockPin(2); 75 | with_close(new gz.DigitalInputDevice(pin), (device) => { 76 | device.when_deactivated = function (){ 77 | event = true; 78 | }; 79 | assert (event === false, "Event is not set to false"); 80 | pin.drive_high(); 81 | assert (event === false, "Event is not set to false"); 82 | pin.drive_low(); 83 | assert (event === true, "Event is not set to true"); 84 | }); 85 | }); 86 | }); 87 | }); -------------------------------------------------------------------------------- /test/mocha.opts: -------------------------------------------------------------------------------- 1 | --reporter spec 2 | --ui bdd 3 | --recursive 4 | --------------------------------------------------------------------------------