├── .editorconfig
├── .gitignore
├── LICENSE
├── README.md
├── lerna.json
├── package.json
└── packages
├── pzgps-angular1
├── .gitignore
├── .jshintrc
├── Gruntfile.js
├── LICENSE
├── README.md
├── bs-config.json
├── package.json
└── src
│ ├── components
│ ├── pzgps-about
│ │ ├── pzgps-about.html
│ │ └── pzgps-about.js
│ ├── pzgps-mapquest
│ │ ├── pzgps-mapquest.html
│ │ └── pzgps-mapquest.js
│ ├── pzgps-navs
│ │ ├── pzgps-navs.html
│ │ └── pzgps-navs.js
│ └── pzgps-websocket
│ │ ├── pzgps-websocket.html
│ │ └── pzgps-websocket.js
│ ├── css
│ └── pzgps.css
│ ├── index.html
│ └── js
│ ├── constants
│ └── urls.js
│ ├── factories
│ ├── intercept.js
│ └── sckt.js
│ └── pzgps.js
├── pzgps-preact
├── .babelrc
├── .eslintignore
├── .eslintrc
├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── package.json
├── src
│ ├── assets
│ │ └── .gitkeep
│ ├── components
│ │ ├── About
│ │ │ └── About.jsx
│ │ ├── App
│ │ │ └── App.jsx
│ │ ├── ContentBox
│ │ │ └── ContentBox.jsx
│ │ ├── GpsData
│ │ │ ├── GpsData.css
│ │ │ └── GpsData.jsx
│ │ ├── KeyValuePair
│ │ │ ├── KeyValuePair.css
│ │ │ └── KeyValuePair.jsx
│ │ ├── ListRoutes
│ │ │ ├── DeleteButton
│ │ │ │ ├── DeleteButton.css
│ │ │ │ └── DeleteButton.jsx
│ │ │ ├── ListRoutes.css
│ │ │ └── ListRoutes.jsx
│ │ ├── MapQuest
│ │ │ ├── MapQuest.css
│ │ │ └── MapQuest.jsx
│ │ ├── NavBar
│ │ │ ├── NavBar.css
│ │ │ └── NavBar.jsx
│ │ ├── NavButton
│ │ │ ├── NavButton.css
│ │ │ └── NavButton.jsx
│ │ └── RouteEditor
│ │ │ ├── CragInput.jsx
│ │ │ ├── RouteEditor.css
│ │ │ └── RouteEditor.jsx
│ ├── index.html
│ ├── index.js
│ ├── lib
│ │ ├── conf.js
│ │ ├── db.js
│ │ ├── ratings.js
│ │ └── sckt.js
│ ├── manifest.json
│ ├── pwa.js
│ └── style
│ │ ├── helpers.less
│ │ ├── index.less
│ │ ├── mixins.less
│ │ └── variables.less
├── test
│ ├── browser
│ │ └── index.js
│ └── karma.conf.js
└── webpack.config.babel.js
├── pzgps-reactjs
├── .babelrc
├── .eslintrc.yml
├── .gitignore
├── .jshintrc
├── LICENSE
├── README.md
├── lib
│ └── sckt.js
├── package.json
├── postcss.config.js
├── src
│ ├── About
│ │ └── about.jsx
│ ├── App
│ │ └── app.jsx
│ ├── ContentBox
│ │ └── ContentBox.jsx
│ ├── GpsData
│ │ ├── GpsData.jsx
│ │ └── gpsdata.scss
│ ├── MapQuest
│ │ ├── MapQuest.jsx
│ │ └── mapquest.scss
│ ├── NavBar
│ │ ├── navbar.jsx
│ │ └── navbar.scss
│ ├── NavButton
│ │ ├── NavButton.jsx
│ │ └── navbutton.scss
│ ├── index.html
│ └── index.jsx
├── webpack.config.js
├── webpack.loaders.js
└── webpack.production.config.js
└── pzgps-server
├── .gitignore
├── LICENSE
├── README.md
├── index.js
├── lib
└── daemon.js
└── package.json
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = tab
5 | end_of_line = lf
6 | charset = utf-8
7 | indent_style = space
8 | indent_size = 2
9 | insert_final_newline = true
10 |
11 | [*.{js,jsx,html,sass}]
12 | trim_trailing_whitespace = true
13 |
14 | [*.md]
15 | trim_trailing_whitespace = false
16 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /npm-debug.log
3 | /lerna-debug.log
4 | /lib/mqkey.js
5 | /default.realm
6 | /default.realm.lock
7 | /default.realm.management/**
8 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
203 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # pzgps
2 | The goal of this project is to collect data from a GPS unit connected to a Raspberry Pi Zero and stream that data out to a web front end via a WebSocket.
3 |
4 | ## Lerna
5 | This project uses [Lerna](https://github.com/lerna/lerna) to manage the server and front end `packages` (in `--independant` mode). If you want to develop anything, you'll need to install Lerna so you can `lerna bootstrap` which will install all of the dependencies for each repo.
6 |
7 | npm install --global lerna
8 |
9 | ## Pull Requests Accepted!
10 | * Please feel free to submit pull requests.
11 | * This project is meant to be a sandbox for learning various things, so expect things to change.
12 | * If this info turns out to be useful to you, [please let me know](https://twitter.com/dankapusta)!
13 |
14 | ## Using the Server Package
15 | The server package, that provides the GPS data over the WebSocket, resides in [`/packages/pzgps-server/`](https://github.com/kapusta/pzgps/tree/master/packages/pzgps-server) and has [a thorough README.md that you should read](https://github.com/kapusta/pzgps/blob/master/packages/pzgps-server/README.md).
16 |
17 | ## Using the Front End Packages
18 |
19 | ### Preact
20 | Currently [the Preact version](https://github.com/kapusta/pzgps/tree/master/packages/pzgps-preact) of the front end has the most code/features/effort.
21 |
22 | Run the webserver with `npm start`.
23 |
24 | Note the `packages/pzgps-preact/src/lib/conf.js` file, which should be modified to match your pizero's name on your network. You can change the name by logging into the pizero, then...
25 | * `raspi-config`
26 | * Go to `Advanced Options`
27 | * Go to `Hostname`
28 | * Type in a new hostname then hit `Ok`
29 |
30 | ### Enabling a MapQuest staticmap
31 | One of the views can load a [Mapquest "staticmap"](http://www.mapquestapi.com/staticmap/) if you have a "Consumer Key" and provide a module from the NodeJS application that includes that key.
32 |
33 | * [Register for a developer account for free](https://developer.mapquest.com/).
34 | * Go to your new profile, and click the "Manage Keys" on the left side menu.
35 | * Click the "Create a New Key" button and provide a name (callback url is not needed for this project).
36 | * You can always find your Consumer Key on the "Manage Keys" page after creating one.
37 | * Make a file in the `/packages/pzgps-server/lib` directory named `mqkey.js` and format it like the example below.
38 |
39 |
40 | module.exports = {
41 | 'consumerKey': 'PASTE YOUR CONSUMER KEY HERE'
42 | };
43 |
44 |
45 | When starting the server use the `--mq` flag. An NPM command is provided in `/packages/pzgps-server/package.json` that will start with the MapQuest module included (eg, `npm run withMapquest` will execute `node index.js --port 9000 --mq`).
46 |
47 | Assuming all of the above is in place, the MapQuest component in the UI will receive the key over the WebSocket and use it to formulate the URL to get the static map. Because the client is receiving updates from the server continually, the map will update if the coordinates change.
48 |
49 |
50 | ### AngularJS
51 | In the `/packages/pzgps-angular1/` directory, run `npm start` to start the [webserver](https://github.com/johnpapa/lite-server). The default port of the webserver can be changed in the `/packages/pzgps-angular1/bs-config.json` file.
52 |
53 |
54 | ### ReactJS
55 | In the `/packages/pzgps-reactjs/` directory, run `npm start` to start the webserver. This project uses [webpack](https://webpack.github.io/) and will auto-reload your browser for you.
56 |
--------------------------------------------------------------------------------
/lerna.json:
--------------------------------------------------------------------------------
1 | {
2 | "lerna": "2.0.0-beta.38",
3 | "packages": [
4 | "packages/*"
5 | ],
6 | "version": "independent"
7 | }
8 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@dankapusta/pzgps",
3 | "version": "3.3.0",
4 | "description": "Read GPS data from a PiZero in a single page web app via a WebSocket",
5 | "keywords": [
6 | "gps"
7 | ],
8 | "scripts": {
9 | "lerna-wizard": "lerna-wizard"
10 | },
11 | "author": "dankapusta",
12 | "license": "Apache-2.0",
13 | "devDependencies": {
14 | "lerna": "2.0.0-beta.38",
15 | "lerna-wizard": "^1.0.6"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/packages/pzgps-angular1/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /www
3 | /tmp
4 |
--------------------------------------------------------------------------------
/packages/pzgps-angular1/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "indent": 2,
3 | "white": false,
4 | "curly": true,
5 | "devel": true,
6 | "eqeqeq": true,
7 | "immed": true,
8 | "latedef": true,
9 | "newcap": false,
10 | "noarg": true,
11 | "sub": true,
12 | "strict": true,
13 | "undef": true,
14 | "boss": true,
15 | "eqnull": true,
16 | "browser": true,
17 | "laxcomma": true
18 | }
19 |
--------------------------------------------------------------------------------
/packages/pzgps-angular1/Gruntfile.js:
--------------------------------------------------------------------------------
1 | module.exports = function (grunt) {
2 |
3 | grunt.loadNpmTasks("grunt-contrib-jshint");
4 | grunt.loadNpmTasks("grunt-contrib-uglify");
5 | grunt.loadNpmTasks("grunt-contrib-watch");
6 | grunt.loadNpmTasks("grunt-contrib-cssmin");
7 | grunt.loadNpmTasks("grunt-contrib-copy");
8 | grunt.loadNpmTasks("grunt-contrib-clean");
9 | grunt.loadNpmTasks("grunt-contrib-concat");
10 | grunt.loadNpmTasks('grunt-angular-templates');
11 | grunt.loadNpmTasks("grunt-ng-annotate");
12 |
13 | // if you simply run "grunt" these default tasks will execute, IN THE ORDER THEY APPEAR!
14 | grunt.registerTask('default', ['jshint', 'clean', 'ngAnnotate', 'ngtemplates', 'uglify', 'concat', 'cssmin', 'copy']);
15 |
16 | grunt.initConfig({
17 | pkg: grunt.file.readJSON('package.json'),
18 |
19 | jshint: {
20 | files: ['./src/js/**/*.js', './src/components/**/*.js'],
21 | options: {
22 | jshintrc: '.jshintrc'
23 | },
24 | },
25 |
26 | clean: {
27 | options: {
28 | force: true, // danger will robinson!
29 | },
30 | target: {
31 | files: [{
32 | expand: true,
33 | cwd: './www/',
34 | src: ['js/**', 'css/**', 'index.html'],
35 | }]
36 | }
37 | },
38 |
39 | ngAnnotate: {
40 | options: {
41 | add: true,
42 | singleQuotes: true
43 | },
44 | pzgps: {
45 | files: {
46 | './tmp/pzgps.annotated.js':
47 | ['./src/js/pzgps.js', './src/js/**/*.js', './src/components/**/*.js']
48 | }
49 | }
50 | },
51 |
52 | // https://github.com/ericclemmons/grunt-angular-templates/blob/master/README.md
53 | ngtemplates: {
54 | 'pzgps': {
55 | cwd: 'src',
56 | src: [
57 | 'components/**/*.html'
58 | ],
59 | dest: 'tmp/pzgps-components.min.js',
60 | options: {
61 | standalone: false,
62 | prefix: '/',
63 | htmlmin: { // NOTE: disable this if anything breaks
64 | collapseWhitespace: true,
65 | removeRedundantAttributes: true,
66 | removeScriptTypeAttributes: true,
67 | removeStyleLinkTypeAttributes: true,
68 | keepClosingSlash: true // needed for SVGs
69 | }
70 | }
71 | }
72 | },
73 |
74 | uglify: {
75 | pzgps: {
76 | options: {
77 | sourceMap: true,
78 | report: 'min'
79 | },
80 | src: ['./tmp/pzgps.annotated.js'],
81 | dest: './tmp/pzgps.uglified.js'
82 | }
83 | },
84 |
85 | concat: {
86 | 'pzgps': {
87 | src: ['<%= uglify.pzgps.dest %>', '<%= ngtemplates.pzgps.dest %>'],
88 | dest: 'tmp/pzgps.min.js'
89 | }
90 | },
91 |
92 | /* (dest : src) */
93 | cssmin: {
94 | compress: {
95 | files: {
96 | './tmp/pzgps.min.css': ['./src/css/pzgps.css']
97 | }
98 | }
99 | },
100 |
101 |
102 | copy: {
103 | idx: {
104 | files: [
105 | {
106 | expand: false,
107 | src: ['./src/index.html'],
108 | dest: './www/index.html',
109 | filter: 'isFile'
110 | }
111 | ]
112 | },
113 | js: {
114 | files: [
115 | {
116 | expand: true,
117 | flatten: true,
118 | src: [
119 | 'tmp/pzgps.min.js',
120 | 'tmp/pzgps.uglified.js.map',
121 | 'node_modules/angular-websocket/dist/angular-websocket.min.js'
122 | ],
123 | dest: './www/js/',
124 | filter: 'isFile'
125 | }
126 | ]
127 | },
128 | css: {
129 | files: [
130 | {
131 | expand: true,
132 | flatten: true,
133 | src: ['tmp/pzgps.min.css'],
134 | dest: './www/css/',
135 | filter: 'isFile'
136 | }
137 | ]
138 | }
139 | },
140 |
141 | watch: {
142 | stuff: {
143 | files: "<%= './src/**/*' %>",
144 | tasks: ["default"]
145 | },
146 | }
147 | });
148 | };
149 |
--------------------------------------------------------------------------------
/packages/pzgps-angular1/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
203 |
--------------------------------------------------------------------------------
/packages/pzgps-angular1/README.md:
--------------------------------------------------------------------------------
1 | # pzgps
2 | =======
3 |
4 | An AngularJS 1.x UI for pzgps
5 |
6 | ## Get Started
7 |
8 | * `sudo npm install -g live-server` an http server, installed globally
9 | * `npm install` - installs your site and build dependencies
10 | * `npm start` - starts a web server using the assets in the `www` directory
11 | * `grunt` - (re)builds the site
12 |
13 | ## License
14 |
15 | Apache Version 2
16 |
--------------------------------------------------------------------------------
/packages/pzgps-angular1/bs-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "port": 9001,
3 | "reloadDebounce": 250,
4 | "files": ["www/**/*.{html,htm,css,js}"],
5 | "server": {
6 | "baseDir": "www",
7 | "index": "index.html"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/packages/pzgps-angular1/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "pzgps-angular1",
3 | "version": "1.0.1",
4 | "description": "pzgps fronted by AngularJS 1.x",
5 | "license": "Apache-2.0",
6 | "author": {
7 | "name": "Daniel Kapusta",
8 | "url": "http://about.me/dankapusta"
9 | },
10 | "scripts": {
11 | "start": "concurrently --kill-others 'lite-server -c bs-config.json' 'grunt watch'",
12 | "server": "lite-server -c bs-config.json"
13 | },
14 | "devDependencies": {
15 | "concurrently": "^3.1.0",
16 | "grunt": "^0.4.5",
17 | "grunt-angular-templates": "^1.1.0",
18 | "grunt-contrib-clean": "^0.6.0",
19 | "grunt-contrib-concat": "^1.0.1",
20 | "grunt-contrib-copy": "^0.8.0",
21 | "grunt-contrib-cssmin": "^0.12.3",
22 | "grunt-contrib-jshint": "^0.11.2",
23 | "grunt-contrib-uglify": "^0.9.1",
24 | "grunt-contrib-watch": "^0.6.1",
25 | "grunt-ng-annotate": "^1.0.1",
26 | "lite-server": "^2.2.2"
27 | },
28 | "dependencies": {
29 | "angular-websocket": "^2.0.1"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/packages/pzgps-angular1/src/components/pzgps-about/pzgps-about.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
pzgps
5 |
6 |
This UI is built with angular 1.x and uses angular-websocket to talk to the websocket server. The URL to the server lives in src/js/constants/urls.js. When you click the Raw GPS Data button, that component will run and the connection the server will be made.
57 |
58 |
59 |
--------------------------------------------------------------------------------
/packages/pzgps-angular1/src/js/constants/urls.js:
--------------------------------------------------------------------------------
1 | (function(angular) {
2 | 'use strict';
3 |
4 | angular.module('pzgps').constant('urls', {
5 | 'gps': 'ws://circ.local:9000',
6 | });
7 |
8 | }(window.angular));
9 |
--------------------------------------------------------------------------------
/packages/pzgps-angular1/src/js/factories/intercept.js:
--------------------------------------------------------------------------------
1 | (function(angular){
2 | 'use strict';
3 |
4 | /**
5 | @name intercept
6 | @memberof pzgps
7 | @ngdoc factory
8 | @description intercepts inbound and outbound http connections
9 | @see https://gist.github.com/gnomeontherun/5678505
10 | */
11 | angular.module('pzgps').factory('intercept', ['$q', '$rootScope', '$log', function($q, $rootScope, $log) {
12 | $log.log("intercept factory is running");
13 |
14 | var request = function(obj) {
15 | // Access to lots of great stuff in here...
16 | // obj.headers (object), obj.method (string), obj.url (string), obj.withCredentials (boolean)
17 | //$log.log("intercept: request");
18 | //$log.log(obj);
19 | // transform the response here if you need to, the request config is in config
20 | return obj || $q.when(obj);
21 | };
22 |
23 | var requestError = function(obj) { // a failed request
24 | //$log.log("intercept: requestError");
25 | //$log.log(obj);
26 | return $q.reject(obj);
27 | };
28 |
29 | var response = function(obj) { // a succuesful response
30 | //$log.log("intercept: response");
31 | //$log.log(obj);
32 | // transform the response here if you need to, the deserialize JSON is in obj.data
33 | return obj || $q.when(obj);
34 | };
35 |
36 | var responseError = function(obj) { // a failed response
37 | $log.log("intercept factory caught an error: " + obj.status);
38 | //$log.log(obj); // this object is handed to $http and .then() fires with the object
39 | return $q.reject(obj);
40 | };
41 |
42 | return {
43 | 'request': request,
44 | 'requestError': requestError,
45 | 'response': response,
46 | 'responseError': responseError
47 | };
48 |
49 | }]);
50 |
51 | }(window.angular));
52 |
--------------------------------------------------------------------------------
/packages/pzgps-angular1/src/js/factories/sckt.js:
--------------------------------------------------------------------------------
1 | (function(angular){
2 | 'use strict';
3 |
4 | /**
5 | @name sckt
6 | @memberof pzgps
7 | @ngdoc factory
8 | @description uses the $websocket service to provide reuseable sockets to components
9 | */
10 | angular.module('pzgps').factory('sckt', function($q, $rootScope, $log, $websocket) {
11 | $log.log("sckt factory is running");
12 |
13 | var sockets = {};
14 |
15 | var connect = function(url) {
16 | var b64 = window.btoa(url);
17 | if (sockets[b64]) {
18 | sockets[b64].connections++;
19 | return sockets[b64];
20 | } else {
21 | var socket = $websocket(url);
22 | sockets[b64] = {
23 | 'socket': socket,
24 | 'connections' : 1
25 | };
26 | return sockets[b64];
27 | }
28 | };
29 |
30 | var disconnect = function(url) {
31 | var b64 = window.btoa(url);
32 | if (sockets[b64]) {
33 | sockets[b64].connections--;
34 | }
35 | if (!sockets[b64].connections) {
36 | sockets[b64].socket.close();
37 | delete sockets[b64];
38 | }
39 | $log.log(Object.keys(sockets).length, 'sockets');
40 | };
41 |
42 | return {
43 | 'connect': connect,
44 | 'disconnect': disconnect
45 | };
46 |
47 | });
48 |
49 | }(window.angular));
50 |
--------------------------------------------------------------------------------
/packages/pzgps-angular1/src/js/pzgps.js:
--------------------------------------------------------------------------------
1 | (function(angular) {
2 | 'use strict'; // ECMA5 strict mode
3 |
4 | var pzgps = angular.module('pzgps', ['ngRoute', 'ngWebSocket']);
5 |
6 | // Configure the module.
7 | pzgps.config(function($routeProvider, $locationProvider, $httpProvider) {
8 | var baseUrl = '/';
9 |
10 | $locationProvider.html5Mode(true);
11 |
12 | $routeProvider
13 | .when(baseUrl, {
14 | template: function(params){
15 | return '';
16 | }
17 | })
18 | .when(baseUrl + ':component', {
19 | template: function(params){
20 | return '';
21 | }
22 | })
23 | .otherwise({redirectTo: baseUrl});
24 |
25 | });
26 |
27 | pzgps.run(function($routeParams, $route, $rootScope, $http, $location) {
28 |
29 | $http.defaults.headers.get = {
30 | 'Content-Type': 'application/json'
31 | };
32 |
33 | $rootScope.$on('$routeChangeError', function (event, current, previous, rejection) {
34 | $location.replace().path($rootScope.baseUrl);
35 | });
36 |
37 | });
38 |
39 | }(window.angular));
40 |
--------------------------------------------------------------------------------
/packages/pzgps-preact/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "sourceMaps": true,
3 | "presets": [
4 | "es2015-minimal",
5 | "stage-0"
6 | ],
7 | "plugins": [
8 | ["transform-decorators-legacy"],
9 | ["transform-react-jsx", { "pragma": "h" }]
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/packages/pzgps-preact/.eslintignore:
--------------------------------------------------------------------------------
1 | test/*.conf.js
2 |
--------------------------------------------------------------------------------
/packages/pzgps-preact/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "parser": "babel-eslint",
3 | "extends": "eslint:recommended",
4 | "env": {
5 | "browser": true,
6 | "node": true,
7 | "mocha": true,
8 | "es6": true
9 | },
10 | "parserOptions": {
11 | "ecmaFeatures": {
12 | "modules": true,
13 | "jsx": true
14 | }
15 | },
16 | "globals": {},
17 | "rules": {
18 | "no-empty": 0,
19 | "no-console": 0,
20 | "no-unused-vars": [0, { "varsIgnorePattern": "^h$" }],
21 | "no-cond-assign": 1,
22 | "semi": [2, "always"],
23 | "camelcase": 0,
24 | "comma-style": 2,
25 | "comma-dangle": [2, "never"],
26 | "indent": ["error", 2],
27 | "no-mixed-spaces-and-tabs": [2, "smart-tabs"],
28 | "no-trailing-spaces": [2, { "skipBlankLines": true }],
29 | "max-nested-callbacks": [2, 3],
30 | "no-eval": 2,
31 | "no-implied-eval": 2,
32 | "no-new-func": 2,
33 | "guard-for-in": 2,
34 | "eqeqeq": 1,
35 | "no-else-return": 2,
36 | "no-redeclare": 2,
37 | "no-dupe-keys": 2,
38 | "radix": 2,
39 | "strict": [2, "never"],
40 | "no-shadow": 0,
41 | "no-delete-var": 2,
42 | "no-undef-init": 2,
43 | "no-shadow-restricted-names": 2,
44 | "handle-callback-err": 0,
45 | "no-lonely-if": 2,
46 | "keyword-spacing": 2,
47 | "constructor-super": 2,
48 | "no-this-before-super": 2,
49 | "no-dupe-class-members": 2,
50 | "no-const-assign": 2,
51 | "prefer-spread": 2,
52 | "no-useless-concat": 2,
53 | "no-var": 2,
54 | "object-shorthand": 2,
55 | "prefer-arrow-callback": 2
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/packages/pzgps-preact/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /npm-debug.log
3 | /build
4 | .DS_Store
5 |
--------------------------------------------------------------------------------
/packages/pzgps-preact/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - 4
4 |
--------------------------------------------------------------------------------
/packages/pzgps-preact/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
203 |
--------------------------------------------------------------------------------
/packages/pzgps-preact/README.md:
--------------------------------------------------------------------------------
1 | # pzgps-preact
2 |
3 | This [Preact based](https://github.com/developit/preact-boilerplate) UI is intended to be used with [pzgps-server](https://github.com/kapusta/pzgps/tree/master/packages/pzgps-server). Please see that package's [README](https://github.com/kapusta/pzgps/blob/master/packages/pzgps-server/README.md) for more information.
4 |
5 | ---
6 |
7 |
8 | # Quick-Start Guide
9 |
10 | - [Installation](#installation)
11 | - [Development Workflow](#development)
12 | - [Production Build](#production-build)
13 | - [Lint Your Code](#lint-your-code)
14 | - [Testing](#testing)
15 | - [CSS Modules](#css-modules)
16 | - [Handling URLS](#handling-urls)
17 | - [License](#license)
18 |
19 |
20 | ## Installation
21 |
22 | npm install
23 |
24 |
25 | ## Development
26 |
27 | Start a live-reload development server
28 |
29 | npm start
30 |
31 |
32 | This is a full web server nicely suited to your project. Any time you make changes within the `src` directory, it will rebuild and even refresh your browser.
33 |
34 |
35 | ## Production Build
36 |
37 | npm run build
38 |
39 |
40 | You can now deploy the contents of the `build` directory to production!
41 |
42 |
43 | ## Lint Your Code
44 |
45 | npm run lint
46 |
47 |
48 | ## Testing
49 |
50 | npm test
51 |
52 |
53 | ## CSS Modules
54 |
55 | This project is set up to support [CSS Modules](https://github.com/css-modules/css-modules). By default, styles in `src/style` are **global** (not using CSS Modules) to make global declarations, imports and helpers easy to declare. Styles in `src/components` are loaded as CSS Modules via [Webpack's css-loader](https://github.com/webpack/css-loader#css-modules). Modular CSS namespaces class names, and when imported into JavaScript returns a mapping of canonical (unmodified) CSS classes to their local (namespaced/suffixed) counterparts.
56 |
57 | When imported, this LESS/CSS:
58 |
59 | ```css
60 | .redText { color:red; }
61 | .blueText { color:blue; }
62 | ```
63 |
64 | ... returns the following map:
65 |
66 | ```js
67 | import styles from './style.css';
68 | console.log(styles);
69 | // {
70 | // redText: 'redText_local_9gt72',
71 | // blueText: 'blueText_local_9gt72'
72 | // }
73 | ```
74 |
75 | Note that the suffix for local classNames is generated based on an md5 hash of the file. Changing the file changes the hash.
76 |
77 |
78 | ## Handling URLS
79 |
80 | :information_desk_person: This project contains a basic two-page app with [URL routing](http://git.io/preact-router).
81 |
82 | Pages are just regular components that get mounted when you navigate to a certain URL. Any URL parameters get passed to the component as `props`.
83 |
84 | Defining what component(s) to load for a given URL is easy and declarative. You can even mix-and-match URL parameters and normal props.
85 |
86 | ```js
87 |
88 |
89 |
90 |
91 |
92 | ```
93 |
94 |
95 | ---
96 |
97 |
98 | ## License
99 |
100 | Apache 2.0
101 |
--------------------------------------------------------------------------------
/packages/pzgps-preact/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "pzgps-preact",
3 | "version": "1.1.5",
4 | "description": "pzgps fronted by Preact.",
5 | "scripts": {
6 | "start": "cross-env NODE_ENV=development webpack-dev-server --inline --hot --progress",
7 | "build": "cross-env NODE_ENV=production webpack -p --progress",
8 | "prebuild": "mkdirp build && ncp src/assets build/assets",
9 | "test": "npm run -s lint && npm run -s test:karma",
10 | "test:karma": "karma start test/karma.conf.js --single-run",
11 | "lint": "eslint --ext .js src --ext .js,.jsx || exit 0"
12 | },
13 | "keywords": [
14 | "preact",
15 | "pzgps",
16 | "gps"
17 | ],
18 | "license": "Apache-2.0",
19 | "contributors": [
20 | {
21 | "name": "Jason Miller",
22 | "email": "jason@developit.ca"
23 | },
24 | {
25 | "name": "Daniel Kapusta",
26 | "email": "kapusta@gmail.com",
27 | "url": "https://github.com/kapusta/"
28 | }
29 | ],
30 | "devDependencies": {
31 | "autoprefixer": "^6.4.0",
32 | "babel": "^6.5.2",
33 | "babel-core": "^6.23.1",
34 | "babel-eslint": "^7.1.1",
35 | "babel-loader": "^6.2.5",
36 | "babel-plugin-transform-decorators-legacy": "^1.3.4",
37 | "babel-plugin-transform-react-jsx": "^6.8.0",
38 | "babel-preset-es2015": "^6.22.0",
39 | "babel-preset-es2015-minimal": "^2.1.0",
40 | "babel-preset-stage-0": "^6.22.0",
41 | "babel-register": "^6.18.0",
42 | "babel-runtime": "^6.23.0",
43 | "chai": "^3.5.0",
44 | "copy-webpack-plugin": "^4.0.1",
45 | "core-js": "^2.4.1",
46 | "cross-env": "^2.0.0",
47 | "css-loader": "^0.25.0",
48 | "eslint": "^6.7.2",
49 | "extract-text-webpack-plugin": "^1.0.1",
50 | "file-loader": "^0.9.0",
51 | "html-webpack-plugin": "^2.22.0",
52 | "json-loader": "^0.5.4",
53 | "karma": "^1.0.0",
54 | "karma-chai": "^0.1.0",
55 | "karma-chai-sinon": "^0.1.5",
56 | "karma-mocha": "^1.0.1",
57 | "karma-mocha-reporter": "^2.1.0",
58 | "karma-phantomjs-launcher": "^1.0.2",
59 | "karma-sourcemap-loader": "^0.3.7",
60 | "karma-webpack": "^1.8.0",
61 | "less": "^2.7.1",
62 | "less-loader": "^2.2.3",
63 | "mkdirp": "^0.5.1",
64 | "mocha": "^3.0.0",
65 | "ncp": "^2.0.0",
66 | "offline-plugin": "^4.5.5",
67 | "path": "^0.12.7",
68 | "phantomjs-prebuilt": "^2.1.12",
69 | "postcss-loader": "^1.2.0",
70 | "raw-loader": "^0.5.1",
71 | "sinon": "^1.17.5",
72 | "sinon-chai": "^2.8.0",
73 | "source-map-loader": "^0.1.5",
74 | "style-loader": "^0.13.0",
75 | "superstatic": "^4.0.3",
76 | "url-loader": "^0.5.7",
77 | "webpack": "^1.14.0",
78 | "webpack-dev-server": "^1.16.2"
79 | },
80 | "dependencies": {
81 | "bootstrap": "^4.0.0-alpha.6",
82 | "classnames": "^2.2.5",
83 | "font-awesome": "^4.7.0",
84 | "haversine": "^1.0.2",
85 | "lodash": "^4.17.4",
86 | "pouchdb": "^6.1.1",
87 | "preact": "^7.1.0",
88 | "preact-compat": "^3.9.4",
89 | "preact-router": "^2.3.2",
90 | "proptypes": "^0.14.3",
91 | "react-select": "^1.0.0-rc.2",
92 | "shortid": "^2.2.6"
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/packages/pzgps-preact/src/assets/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kapusta/pzgps/854a07650f1d59a139c484ca1c0f16d9e266508d/packages/pzgps-preact/src/assets/.gitkeep
--------------------------------------------------------------------------------
/packages/pzgps-preact/src/components/About/About.jsx:
--------------------------------------------------------------------------------
1 | import { h, Component } from 'preact';
2 |
3 | class About extends Component {
4 | constructor(props) {
5 | super(props);
6 | }
7 | render() {
8 | return (
9 |
10 |
11 |
About
12 |
13 |
14 | This is a Preact implementation of the GPS front end based on the preact-boilerplate project.
15 |
16 |
17 | If the server on the pizero is set up correctly, more buttons will appear above after establishing the WebSocket connection.
18 |
336 | );
337 | }
338 | }
339 |
340 | export default RouteEditor;
341 |
--------------------------------------------------------------------------------
/packages/pzgps-preact/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | pzgps
6 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/packages/pzgps-preact/src/index.js:
--------------------------------------------------------------------------------
1 | import 'bootstrap/dist/css/bootstrap.min.css';
2 | import 'font-awesome/css/font-awesome.min.css';
3 | import 'react-select/dist/react-select.css';
4 | import './style';
5 | import { h, render } from 'preact';
6 | import App from './components/App/App.jsx';
7 |
8 | let root;
9 |
10 | function init() {
11 | console.log('initializing app');
12 | root = render(
13 | ,
14 | document.querySelector("#app"),
15 | root
16 | );
17 | }
18 |
19 | // register ServiceWorker via OfflinePlugin, for prod only:
20 | if (process.env.NODE_ENV==='production') {
21 | require('./pwa.js');
22 | }
23 |
24 | // in development, set up HMR:
25 | if (module.hot) {
26 | //require('preact/devtools'); // turn this on if you want to enable React DevTools!
27 | module.hot.accept('./components/App/App.jsx', () => requestAnimationFrame(init) );
28 | }
29 |
30 | init();
31 |
--------------------------------------------------------------------------------
/packages/pzgps-preact/src/lib/conf.js:
--------------------------------------------------------------------------------
1 | // change these values to match your environment
2 | export default {
3 | 'socketServer': 'ws://pzgps.local:9000',
4 | 'couchdb': 'http://pzgps.local:5984'
5 | };
6 |
--------------------------------------------------------------------------------
/packages/pzgps-preact/src/lib/db.js:
--------------------------------------------------------------------------------
1 | /* global emit */
2 | import conf from './conf.js';
3 | import PouchDB from 'pouchdb';
4 |
5 | let databases = {};
6 | let cancelSync = name => {
7 | databases[name + '-sync'].cancel();
8 | };
9 |
10 | // these could get a bit out of hand overtime, consider moving out to separate files
11 | let queries = {
12 | routes: {
13 | _id: '_design/routes',
14 | views: {
15 | by_name: {
16 | map: function (doc) { emit(doc.name); }.toString()
17 | }
18 | }
19 | },
20 | boulders: {
21 | _id: '_design/boulders',
22 | views: {
23 | by_name: {
24 | map: function (doc) { emit(doc.name); }.toString()
25 | }
26 | }
27 | },
28 | crags: {
29 | _id: '_design/crags',
30 | views: {
31 | by_name: {
32 | map: function (doc) { emit(doc.name); }.toString()
33 | }
34 | }
35 | }
36 | };
37 |
38 | const init = () => {
39 | ['routes', 'boulders', 'crags'].forEach(name => {
40 | console.log('Initializing ' + name + ' database...');
41 | databases[name + '-local'] = new PouchDB(name);
42 | databases[name + '-remote'] = new PouchDB(conf.couchdb + '/' + name);
43 | databases[name + '-sync'] = databases[name + '-local'].sync(databases[name + '-remote'], {
44 | live: true,
45 | retry: true
46 | }).on('complete', n => {
47 | console.log('local/remote database synced', n);
48 | }).on('error', err => {
49 | console.error('replication error', err);
50 | });
51 | });
52 |
53 | Object.keys(queries).forEach(q => {
54 | databases[q + '-local'].put(queries[q]).then(() => {
55 | console.log('PUT query into db', q);
56 | }).catch(err => {
57 | if (err.status !== 409) {
58 | console.error('FAILED to PUT query into db', err);
59 | }
60 | });
61 | });
62 |
63 | };
64 |
65 |
66 | export default {
67 | cancelSync,
68 | databases,
69 | init
70 | };
71 |
--------------------------------------------------------------------------------
/packages/pzgps-preact/src/lib/ratings.js:
--------------------------------------------------------------------------------
1 | /**
2 | @description lets of things in ready to consume format for react-select
3 | @see https://en.wikipedia.org/wiki/Grade_(climbing)
4 | */
5 | const yds = new Array(16).fill(0).map((val, idx) => {
6 | return {
7 | 'value': '5.' + idx,
8 | 'label': '5.' + idx
9 | };
10 | });
11 |
12 | const hueco = new Array(18).fill(0).map((val, idx) => {
13 | return {
14 | 'value': 'V' + idx,
15 | 'label': 'V' + idx
16 | };
17 | });
18 |
19 | const routeTypes = ['trad', 'sport', 'mixed', 'boulder', 'ice'].map((val, idx) => {
20 | return {
21 | 'value': val,
22 | 'label': val
23 | };
24 | });
25 |
26 | export {
27 | yds,
28 | hueco,
29 | routeTypes
30 | };
31 |
--------------------------------------------------------------------------------
/packages/pzgps-preact/src/lib/sckt.js:
--------------------------------------------------------------------------------
1 | import {isEqual} from 'lodash';
2 |
3 | const connect = serverUrl => {
4 | return new Promise((resolve, reject) => {
5 | let socket = new WebSocket(serverUrl);
6 | socket.onopen = e => {
7 | console.log('Connected.', e);
8 | return resolve(socket);
9 | };
10 | socket.onerror = e => {
11 | return reject(e);
12 | };
13 | }); // don't need a catch clause here because of the onerror above
14 | };
15 |
16 | // TODO: not purely functional
17 | const init = (serverUrl, Component) => {
18 |
19 | let lastLocation = {}; // location, uses to compare current to previous
20 |
21 | connect(serverUrl).then(socket => {
22 |
23 | Component.setState({
24 | socket
25 | });
26 |
27 | socket.send(JSON.stringify({
28 | 'action': 'pzgps.get.consumerKey'
29 | }));
30 |
31 | socket.onclose = e => {
32 | // https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent
33 | console.error('The WebSocket connection closed', e);
34 | console.log('Trying to reconnect...');
35 | window.setTimeout(() => {
36 | init(serverUrl, Component);
37 | }, 5000);
38 | };
39 |
40 | socket.onmessage = e => {
41 | let data = JSON.parse(e.data);
42 | if (data.consumerKey) {
43 | Component.setState({
44 | consumerKey: data.consumerKey
45 | });
46 | }
47 | if (data.lat && !isEqual(lastLocation, data)) {
48 | Component.setState({
49 | gpsData: data
50 | });
51 | }
52 | };
53 |
54 | }).catch((err) => {
55 | console.error('could not connect to WebSocket server', err);
56 | console.log('Trying to reconnect...');
57 | setTimeout(() => {
58 | init(serverUrl, Component);
59 | }, 5000);
60 | });
61 |
62 | };
63 |
64 | export default {
65 | connect,
66 | init
67 | };
68 |
--------------------------------------------------------------------------------
/packages/pzgps-preact/src/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "pzgps",
3 | "short_name": "pzgps",
4 | "start_url": "./",
5 | "display": "standalone",
6 | "orientation": "portrait",
7 | "background_color": "#fff",
8 | "theme_color": "#00c0ff",
9 | "icons": [
10 | {
11 | "src": "assets/icons/icon-128x128.png",
12 | "sizes": "128x128",
13 | "type": "image/png"
14 | },
15 | {
16 | "src": "assets/icons/icon-144x144.png",
17 | "sizes": "144x144",
18 | "type": "image/png"
19 | },
20 | {
21 | "src": "assets/icons/icon-152x152.png",
22 | "sizes": "152x152",
23 | "type": "image/png"
24 | },
25 | {
26 | "src": "assets/icons/icon-192x192.png",
27 | "sizes": "192x192",
28 | "type": "image/png"
29 | },
30 | {
31 | "src": "assets/icons/icon-256x256.png",
32 | "sizes": "256x256",
33 | "type": "image/png"
34 | }
35 | ]
36 | }
37 |
--------------------------------------------------------------------------------
/packages/pzgps-preact/src/pwa.js:
--------------------------------------------------------------------------------
1 | import runtime from 'offline-plugin/runtime';
2 |
3 | runtime.install({
4 | // When an update is ready, tell ServiceWorker to take control immediately:
5 | onUpdateReady() {
6 | console.log('update ready');
7 | runtime.applyUpdate();
8 | },
9 |
10 | // Reload to get the new version:
11 | onUpdated() {
12 | console.log('updated');
13 | location.reload();
14 | }
15 | });
16 |
--------------------------------------------------------------------------------
/packages/pzgps-preact/src/style/helpers.less:
--------------------------------------------------------------------------------
1 | @import 'variables';
2 | @import 'mixins';
3 |
--------------------------------------------------------------------------------
/packages/pzgps-preact/src/style/index.less:
--------------------------------------------------------------------------------
1 | @import 'helpers';
2 |
3 | html, body {
4 | width: 100%;
5 | padding: 0;
6 | margin: 40px 0px 10px 0px;
7 | background: #FAFAFA;
8 | font-family: 'Helvetica Neue', arial, sans-serif;
9 | font-weight: 400;
10 | color: #444;
11 | -webkit-font-smoothing: antialiased;
12 | -moz-osx-font-smoothing: grayscale;
13 | }
14 |
15 | * {
16 | box-sizing: border-box;
17 | }
18 |
19 | #app {
20 | height: 100%;
21 | }
22 |
--------------------------------------------------------------------------------
/packages/pzgps-preact/src/style/mixins.less:
--------------------------------------------------------------------------------
1 | .fill() {
2 | position: absolute;
3 | left: 0;
4 | top: 0;
5 | width: 100%;
6 | height: 100%;
7 | }
8 |
9 | .scroll() {
10 | overflow: auto;
11 | overflow-scrolling: touch;
12 |
13 | & > .inner {
14 | position: relative;
15 | transform: translateZ(0);
16 | overflow: hidden;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/packages/pzgps-preact/src/style/variables.less:
--------------------------------------------------------------------------------
1 | @red: #F00;
2 | @blue: #00F;
3 | @white: #FFF;
4 | @gray: #999;
5 | @black: #000;
6 |
--------------------------------------------------------------------------------
/packages/pzgps-preact/test/browser/index.js:
--------------------------------------------------------------------------------
1 | import { h, render, rerender } from 'preact';
2 | import { route } from 'preact-router';
3 | import App from 'components/app';
4 | import 'style';
5 |
6 | /*global sinon,expect*/
7 |
8 | describe('App', () => {
9 | let scratch;
10 |
11 | before( () => {
12 | scratch = document.createElement('div');
13 | (document.body || document.documentElement).appendChild(scratch);
14 | });
15 |
16 | beforeEach( () => {
17 | scratch.innerHTML = '';
18 | });
19 |
20 | after( () => {
21 | scratch.parentNode.removeChild(scratch);
22 | scratch = null;
23 | });
24 |
25 |
26 | describe('routing', () => {
27 | it('should render the homepage', () => {
28 | render(, scratch);
29 |
30 | expect(scratch.innerHTML).to.contain('Home');
31 | });
32 |
33 | it('should render /profile', () => {
34 | render(, scratch);
35 | route('/profile');
36 | rerender();
37 |
38 | expect(scratch.innerHTML).to.contain('Profile: me');
39 | });
40 |
41 | it('should render /profile/:user', () => {
42 | render(, scratch);
43 | route('/profile/john');
44 | rerender();
45 |
46 | expect(scratch.innerHTML).to.contain('Profile: john');
47 | });
48 | });
49 | });
50 |
--------------------------------------------------------------------------------
/packages/pzgps-preact/test/karma.conf.js:
--------------------------------------------------------------------------------
1 | require('babel-register');
2 | var webpack = require('../webpack.config.babel.js');
3 |
4 | module.exports = function(config) {
5 | config.set({
6 | basePath: '../',
7 | frameworks: ['mocha', 'chai-sinon'],
8 | reporters: ['mocha'],
9 |
10 | browsers: ['PhantomJS'],
11 |
12 | files: [
13 | 'test/browser/**/*.js'
14 | ],
15 |
16 | preprocessors: {
17 | 'test/**/*.js': ['webpack'],
18 | 'src/**/*.js': ['webpack'],
19 | '**/*.js': ['sourcemap']
20 | },
21 |
22 | webpack: webpack,
23 | webpackMiddleware: { noInfo: true }
24 | });
25 | };
26 |
--------------------------------------------------------------------------------
/packages/pzgps-preact/webpack.config.babel.js:
--------------------------------------------------------------------------------
1 | import webpack from 'webpack';
2 | import ExtractTextPlugin from 'extract-text-webpack-plugin';
3 | import HtmlWebpackPlugin from 'html-webpack-plugin';
4 | import autoprefixer from 'autoprefixer';
5 | import path from 'path';
6 | import CopyWebpackPlugin from 'copy-webpack-plugin';
7 | import OfflinePlugin from 'offline-plugin';
8 |
9 | const ENV = process.env.NODE_ENV || 'development';
10 |
11 | const CSS_MAPS = ENV!=='production';
12 |
13 | module.exports = {
14 | context: path.resolve(__dirname, "src"),
15 | entry: './index.js',
16 |
17 | output: {
18 | path: path.resolve(__dirname, "build"),
19 | publicPath: '/',
20 | filename: 'bundle.js'
21 | },
22 |
23 | resolve: {
24 | extensions: ['', '.jsx', '.js', '.json', '.less'],
25 | modulesDirectories: [
26 | path.resolve(__dirname, "src/lib"),
27 | path.resolve(__dirname, "node_modules"),
28 | 'node_modules'
29 | ],
30 | alias: {
31 | components: path.resolve(__dirname, "src/components"), // used for tests
32 | style: path.resolve(__dirname, "src/style"),
33 | 'react': 'preact-compat',
34 | 'react-dom': 'preact-compat'
35 | }
36 | },
37 |
38 | module: {
39 | preLoaders: [
40 | {
41 | test: /\.jsx?$/,
42 | exclude: /src\//,
43 | loader: 'source-map'
44 | }
45 | ],
46 | loaders: [
47 | {
48 | test: /\.jsx?$/,
49 | exclude: /node_modules/,
50 | loader: 'babel'
51 | },
52 | {
53 | test: /\.(less|css)$/,
54 | include: /src\/components\//,
55 | loader: ExtractTextPlugin.extract('style?singleton', [
56 | `css?sourceMap=${CSS_MAPS}&modules&importLoaders=1&localIdentName=[local]${process.env.CSS_MODULES_IDENT || '_[hash:base64:5]'}`,
57 | 'postcss',
58 | `less?sourceMap=${CSS_MAPS}`
59 | ].join('!'))
60 | },
61 | {
62 | test: /\.(less|css)$/,
63 | exclude: /src\/components\//,
64 | loader: ExtractTextPlugin.extract('style?singleton', [
65 | `css?sourceMap=${CSS_MAPS}`,
66 | `postcss`,
67 | `less?sourceMap=${CSS_MAPS}`
68 | ].join('!'))
69 | },
70 | {
71 | test: /\.json$/,
72 | loader: 'json'
73 | },
74 | {
75 | test: /\.(xml|html|txt|md)$/,
76 | loader: 'raw'
77 | },
78 | {
79 | test: /\.(svg|woff2?|ttf|eot|jpe?g|png|gif)(\?.*)?$/i,
80 | loader: ENV==='production' ? 'file?name=[path][name]_[hash:base64:5].[ext]' : 'url'
81 | }
82 | ]
83 | },
84 |
85 | postcss: () => [
86 | autoprefixer({ browsers: 'last 2 versions' })
87 | ],
88 |
89 | plugins: ([
90 | new webpack.NoErrorsPlugin(),
91 | new ExtractTextPlugin('style.css', {
92 | allChunks: true,
93 | disable: ENV!=='production'
94 | }),
95 | new webpack.optimize.DedupePlugin(),
96 | new webpack.DefinePlugin({
97 | 'process.env': JSON.stringify({ NODE_ENV: ENV })
98 | }),
99 | new HtmlWebpackPlugin({
100 | template: './index.html',
101 | minify: { collapseWhitespace: true }
102 | }),
103 | new CopyWebpackPlugin([
104 | { from: './manifest.json', to: './' }
105 | ]),
106 | new OfflinePlugin({
107 | relativePaths: false,
108 | AppCache: false,
109 | publicPath: '/'
110 | })
111 | ]).concat(ENV==='production' ? [
112 | new webpack.optimize.OccurenceOrderPlugin()
113 | ] : []),
114 |
115 | stats: { colors: true },
116 |
117 | node: {
118 | global: true,
119 | process: false,
120 | Buffer: false,
121 | __filename: false,
122 | __dirname: false,
123 | setImmediate: false
124 | },
125 |
126 | devtool: ENV==='production' ? 'source-map' : 'cheap-module-eval-source-map',
127 |
128 | devServer: {
129 | port: process.env.PORT || 9001,
130 | host: 'localhost',
131 | colors: true,
132 | publicPath: '/',
133 | contentBase: './src',
134 | historyApiFallback: true,
135 | open: true,
136 | proxy: {
137 | // OPTIONAL: proxy configuration:
138 | // '/optional-prefix/**': { // path pattern to rewrite
139 | // target: 'http://target-host.com',
140 | // pathRewrite: path => path.replace(/^\/[^\/]+\//, '') // strip first path segment
141 | // }
142 | }
143 | }
144 | };
145 |
--------------------------------------------------------------------------------
/packages/pzgps-reactjs/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["es2015", "react", "stage-1"]
3 | }
4 |
--------------------------------------------------------------------------------
/packages/pzgps-reactjs/.eslintrc.yml:
--------------------------------------------------------------------------------
1 | ---
2 | extends:
3 | - plugin:react/recommended
4 |
5 | env:
6 | browser: true
7 | node: true
8 | es6: true
9 |
10 | parser: babel-eslint
11 |
12 | parserOptions:
13 | ecmaVersion: 6
14 | sourceType: "module"
15 | ecmaFeatures:
16 | jsx: true
17 |
18 | globals:
19 | __DEV__: true
20 | __SERVER__: true
21 |
22 | plugins:
23 | - react
24 |
25 | rules:
26 | react/jsx-uses-vars: 1
27 | react/prop-types: [1, { ignore: [children] }]
28 |
29 | semi: 0
30 | key-spacing: 1
31 | curly: 0
32 | consistent-return: 0
33 | space-infix-ops: 1
34 | camelcase: 0
35 | no-spaced-func: 1
36 | no-alert: 1
37 | eol-last: 1
38 | comma-spacing: 1
39 | eqeqeq: 1
40 |
41 | # possible errors
42 | comma-dangle: 0
43 | no-cond-assign: 2
44 | no-console: 0
45 | no-constant-condition: 2
46 | no-control-regex: 2
47 | no-debugger: 2
48 | no-dupe-args: 2
49 | no-dupe-keys: 2
50 | no-duplicate-case: 2
51 | no-empty-character-class: 2
52 | no-empty: 2
53 | no-ex-assign: 2
54 | no-extra-boolean-cast: 2
55 | no-extra-parens: 0
56 | no-extra-semi: 2
57 | no-func-assign: 2
58 | no-inner-declarations: 2
59 | no-invalid-regexp: 2
60 | no-irregular-whitespace: 2
61 | no-negated-in-lhs: 2
62 | no-obj-calls: 2
63 | no-regex-spaces: 2
64 | no-sparse-arrays: 2
65 | no-unexpected-multiline: 2
66 | no-unreachable: 2
67 | use-isnan: 2
68 | valid-jsdoc: 2
69 | valid-typeof: 2
70 |
71 | no-redeclare: 2
72 |
73 | init-declarations: 2
74 | no-catch-shadow: 2
75 | no-delete-var: 2
76 | no-label-var: 2
77 | no-shadow-restricted-names: 2
78 | no-shadow: 2
79 | no-undef-init: 2
80 | no-undef: 2
81 | no-undefined: 2
82 | no-unused-vars: 2
83 | no-use-before-define: 2
84 |
--------------------------------------------------------------------------------
/packages/pzgps-reactjs/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 |
5 | # Runtime data
6 | pids
7 | *.pid
8 | *.seed
9 |
10 | # Directory for instrumented libs generated by jscoverage/JSCover
11 | lib-cov
12 |
13 | # Coverage directory used by tools like istanbul
14 | coverage
15 |
16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
17 | .grunt
18 |
19 | # node-waf configuration
20 | .lock-wscript
21 |
22 | # Compiled binary addons (http://nodejs.org/api/addons.html)
23 | build/Release
24 |
25 | # Dependency directory
26 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
27 | node_modules
28 |
29 | # Ignore build files
30 | public
31 |
--------------------------------------------------------------------------------
/packages/pzgps-reactjs/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "esversion": 6
3 | }
4 |
--------------------------------------------------------------------------------
/packages/pzgps-reactjs/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
203 |
--------------------------------------------------------------------------------
/packages/pzgps-reactjs/README.md:
--------------------------------------------------------------------------------
1 | # react-webpack-babel
2 | Simple React Webpack Babel Starter Kit
3 |
4 | Tired of complicated starters with 200MB of dependencies which are hard to understand and modify?
5 |
6 | Try this is a simple [React](https://facebook.github.io/react/), [Webpack](http://webpack.github.io/) and [Babel](https://babeljs.io/) application with nothing else in it.
7 |
8 | ### What's in it?
9 |
10 | * Simple src/index.jsx and src/index.css (local module css).
11 | * Webpack configuration for development (with hot reloading) and production (with minification).
12 | * CSS module loading, so you can include your css by ```import styles from './path/to.css';```.
13 | * Both js(x) and css hot loaded during development.
14 |
15 | ### To run
16 |
17 | * You'll need to have [git](https://git-scm.com/) and [node](https://nodejs.org/en/) installed in your system.
18 | * Fork and clone the project:
19 |
20 | ```
21 | > $ git clone THIS_REPO_URL
22 | ```
23 |
24 | * Then install the dependencies:
25 |
26 | ```
27 | > $ npm install
28 | ```
29 |
30 | * Run development server:
31 |
32 | ```
33 | > $ npm start
34 | ```
35 |
36 | Open the web browser to `http://localhost:8888/`
37 |
38 | ### To build production package
39 |
40 | ```
41 | > $ npm run build
42 | ```
43 |
44 | ### Nginx Config
45 |
46 | Here is the suggested Nginx config:
47 | ```
48 | server {
49 | # ... root and other options
50 |
51 | gzip on;
52 | gzip_http_version 1.1;
53 | gzip_types text/plain text/css text/xml application/javascript image/svg+xml;
54 |
55 | location ~ \.html?$ {
56 | expires 1d;
57 | }
58 |
59 | location ~ \.(svg|ttf|js|css|svgz|eot|otf|woff|jpg|jpeg|gif|png|ico)$ {
60 | access_log off;
61 | log_not_found off;
62 | expires max;
63 | }
64 | }
65 | ```
66 |
67 | ### Eslint
68 | There is a .eslint.yaml config for eslint ready with React plugin.
69 | To use it, you need to install additional dependencies though:
70 |
71 | ```
72 | > npm install --save-dev eslint eslint-plugin-react
73 | ```
74 |
75 | To do the actual linting, run:
76 |
77 | ```
78 | > npm run lint
79 | ```
80 |
81 | ### Notes on importing css styles
82 | * styles having /src/ in their absolute path are considered part of the application and exported as local css modules.
83 | * styles having /node_modules|global/ in their absolute path are considered global styles used by many components and are included in the css bundle directly.
84 |
85 | ### Contribute
86 | Please contribute to the project if you think this can be done better in anyway even for this README :)
87 |
--------------------------------------------------------------------------------
/packages/pzgps-reactjs/lib/sckt.js:
--------------------------------------------------------------------------------
1 | const connect = serverUrl => {
2 | return new Promise((resolve, reject) => {
3 | let socket = new WebSocket(serverUrl);
4 | socket.onopen = e => {
5 | console.log('Connected.', e);
6 | return resolve(socket);
7 | };
8 | socket.onerror = e => {
9 | return reject(e);
10 | };
11 | }); // don't need a catch clause here because of the onerror above
12 | };
13 |
14 | // TODO: not purely functional
15 | const setUpSocket = (serverUrl, Component) => {
16 |
17 | connect(serverUrl).then(socket => {
18 |
19 | Component.setState({
20 | socket
21 | });
22 |
23 | socket.send(JSON.stringify({
24 | 'action': 'pzgps.get.consumerKey'
25 | }));
26 |
27 | socket.onclose = e => {
28 | // https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent
29 | console.error('The WebSocket connection closed', e);
30 | console.log('Trying to reconnect...');
31 | window.setTimeout(() => {
32 | setUpSocket(Component);
33 | }, 5000);
34 | };
35 |
36 | socket.onmessage = e => {
37 | let data = JSON.parse(e.data);
38 | if (data.consumerKey) {
39 | Component.setState({
40 | consumerKey: data.consumerKey
41 | });
42 | } else {
43 | Component.setState({
44 | gpsData: data
45 | });
46 | }
47 | };
48 |
49 | }).catch((err) => {
50 | console.error('could not connect to WebSocket server', err);
51 | console.log('Trying to reconnect...');
52 | setTimeout(() => {
53 | setUpSocket(Component);
54 | }, 5000);
55 | });
56 |
57 | };
58 |
59 | module.exports = {
60 | connect,
61 | setUpSocket
62 | };
63 |
--------------------------------------------------------------------------------
/packages/pzgps-reactjs/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "pzgps-reactjs",
3 | "version": "1.0.1",
4 | "description": "pzgps fronted by ReactJS",
5 | "main": "''",
6 | "scripts": {
7 | "build": "webpack --config webpack.production.config.js --progress --profile --colors",
8 | "start": "webpack-dev-server --progress --profile --colors",
9 | "lint": "eslint --ext .js lib --ext js --ext jsx src || exit 0"
10 | },
11 | "contributors": [
12 | {
13 | "name": "Ali Al Dallal"
14 | },
15 | {
16 | "name": "Daniel Kapusta",
17 | "email": "kapusta@gmail.com",
18 | "url": "https://github.com/kapusta/"
19 | }
20 | ],
21 | "license": "Apache-2.0",
22 | "dependencies": {
23 | "bootstrap": "^4.0.0-alpha.3",
24 | "node-sass": "^4.14.1",
25 | "react": "15.3.2",
26 | "react-dom": "15.3.2",
27 | "react-router": "^3.0.0",
28 | "sass-loader": "^4.0.2",
29 | "shortid": "^2.2.6"
30 | },
31 | "devDependencies": {
32 | "babel-core": "^6.18.2",
33 | "babel-eslint": "^7.1.1",
34 | "babel-loader": "^6.2.7",
35 | "babel-plugin-transform-class-properties": "^6.16.0",
36 | "babel-plugin-transform-decorators-legacy": "^1.3.4",
37 | "babel-plugin-transform-runtime": "^6.15.0",
38 | "babel-preset-es2015": "^6.18.0",
39 | "babel-preset-react": "6.16.0",
40 | "babel-preset-stage-1": "^6.16.0",
41 | "babel-runtime": "^6.18.0",
42 | "css-loader": "0.25.0",
43 | "eslint-plugin-react": "^6.6.0",
44 | "extract-text-webpack-plugin": "^1.0.1",
45 | "file-loader": "0.9.0",
46 | "html-webpack-plugin": "^2.22.0",
47 | "postcss-loader": "^1.0.0",
48 | "react-hot-loader": "^3.0.0-beta.6",
49 | "style-loader": "0.13.1",
50 | "url-loader": "0.5.7",
51 | "webpack": "1.13.2",
52 | "webpack-cleanup-plugin": "^0.4.1",
53 | "webpack-dev-server": "1.16.2"
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/packages/pzgps-reactjs/postcss.config.js:
--------------------------------------------------------------------------------
1 | const AUTOPREFIXER_BROWSERS = [
2 | 'Android 2.3',
3 | 'Android >= 4',
4 | 'Chrome >= 35',
5 | 'Firefox >= 31',
6 | 'Explorer >= 9',
7 | 'iOS >= 7',
8 | 'Opera >= 12',
9 | 'Safari >= 7.1',
10 | ];
11 |
12 | module.exports = {
13 | plugins: [
14 | require('autoprefixer')({ browsers: AUTOPREFIXER_BROWSERS })
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/packages/pzgps-reactjs/src/About/about.jsx:
--------------------------------------------------------------------------------
1 | import 'bootstrap/dist/css/bootstrap.min.css';
2 | //import styles from '../index.scss';
3 | import React from 'react';
4 |
5 | class About extends React.Component {
6 | constructor(props) {
7 | super(props);
8 | }
9 | render() {
10 | return (
11 |
12 |
13 |
About
14 |
15 | This is a ReactJS implementation of the GPS front end based on the react-webpack-babel project. If the server on the pizero is set up correctly, a GPS Data and MapQuest button will appear above.
16 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/packages/pzgps-reactjs/src/index.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { render } from 'react-dom';
3 | import App from './App/App.jsx';
4 | import { Router, Route, browserHistory, IndexRoute } from 'react-router';
5 |
6 | render(
7 |
8 |
9 | ,
10 | document.querySelector("#app")
11 | );
12 |
--------------------------------------------------------------------------------
/packages/pzgps-reactjs/webpack.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var webpack = require('webpack');
3 | var path = require('path');
4 | var loaders = require('./webpack.loaders');
5 | var HtmlWebpackPlugin = require('html-webpack-plugin');
6 |
7 | const HOST = process.env.HOST || "127.0.0.1";
8 | const PORT = process.env.PORT || "9001";
9 |
10 | // global css
11 | loaders.push({
12 | test: /[\/\\](node_modules|global)[\/\\].*\.css$/,
13 | loaders: [
14 | 'style?sourceMap',
15 | 'css'
16 | ]
17 | });
18 | // local scss modules
19 | loaders.push({
20 | test: /[\/\\]src[\/\\].*\.scss/,
21 | exclude: /(node_modules|bower_components|public)/,
22 | loaders: [
23 | 'style?sourceMap',
24 | 'css?modules&importLoaders=1&localIdentName=[path]___[name]__[local]___[hash:base64:5]',
25 | 'postcss',
26 | 'sass'
27 | ]
28 | });
29 |
30 | // local css modules
31 | loaders.push({
32 | test: /[\/\\]src[\/\\].*\.css/,
33 | exclude: /(node_modules|bower_components|public)/,
34 | loaders: [
35 | 'style?sourceMap',
36 | 'css?modules&importLoaders=1&localIdentName=[path]___[name]__[local]___[hash:base64:5]'
37 | ]
38 | });
39 |
40 | module.exports = {
41 | entry: [
42 | `webpack-dev-server/client?http://${HOST}:${PORT}`,
43 | `webpack/hot/only-dev-server`,
44 | `./src/index.jsx` // Your appʼs entry point
45 | ],
46 | devtool: process.env.WEBPACK_DEVTOOL || 'cheap-module-source-map',
47 | output: {
48 | path: path.join(__dirname, 'public'),
49 | filename: 'bundle.js'
50 | },
51 | resolve: {
52 | extensions: ['', '.js', '.jsx']
53 | },
54 | module: {
55 | loaders
56 | },
57 | devServer: {
58 | contentBase: "./public",
59 | // do not print bundle build stats
60 | noInfo: true,
61 | // enable HMR
62 | hot: true,
63 | // embed the webpack-dev-server runtime into the bundle
64 | inline: true,
65 | // serve index.html in place of 404 responses to allow HTML5 history
66 | historyApiFallback: true,
67 | port: PORT,
68 | host: HOST
69 | },
70 | plugins: [
71 | new webpack.NoErrorsPlugin(),
72 | new webpack.HotModuleReplacementPlugin(),
73 | new HtmlWebpackPlugin({
74 | template: './src/index.html'
75 | }),
76 | ]
77 | };
78 |
--------------------------------------------------------------------------------
/packages/pzgps-reactjs/webpack.loaders.js:
--------------------------------------------------------------------------------
1 | module.exports = [
2 | {
3 | test: /\.jsx?$/,
4 | exclude: /(node_modules|bower_components|public)/,
5 | loaders: ['react-hot-loader/webpack']
6 | },
7 | {
8 | test: /\.jsx?$/,
9 | exclude: /(node_modules|bower_components|public)/,
10 | loader: 'babel',
11 | query: {
12 | presets: ['es2015', 'react', 'stage-1'],
13 | plugins: ['transform-runtime', 'transform-decorators-legacy', 'transform-class-properties'],
14 | }
15 | },
16 | {
17 | test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
18 | exclude: /(node_modules|bower_components)/,
19 | loader: "file"
20 | },
21 | {
22 | test: /\.(woff|woff2)$/,
23 | exclude: /(node_modules|bower_components)/,
24 | loader: "url?prefix=font/&limit=5000"
25 | },
26 | {
27 | test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
28 | exclude: /(node_modules|bower_components)/,
29 | loader: "url?limit=10000&mimetype=application/octet-stream"
30 | },
31 | {
32 | test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
33 | exclude: /(node_modules|bower_components)/,
34 | loader: "url?limit=10000&mimetype=image/svg+xml"
35 | },
36 | {
37 | test: /\.gif/,
38 | exclude: /(node_modules|bower_components)/,
39 | loader: "url-loader?limit=10000&mimetype=image/gif"
40 | },
41 | {
42 | test: /\.jpg/,
43 | exclude: /(node_modules|bower_components)/,
44 | loader: "url-loader?limit=10000&mimetype=image/jpg"
45 | },
46 | {
47 | test: /\.png/,
48 | exclude: /(node_modules|bower_components)/,
49 | loader: "url-loader?limit=10000&mimetype=image/png"
50 | }
51 | ];
52 |
--------------------------------------------------------------------------------
/packages/pzgps-reactjs/webpack.production.config.js:
--------------------------------------------------------------------------------
1 |
2 | var webpack = require('webpack');
3 | var path = require('path');
4 | var loaders = require('./webpack.loaders');
5 | var ExtractTextPlugin = require('extract-text-webpack-plugin');
6 | var HtmlWebpackPlugin = require('html-webpack-plugin');
7 | var WebpackCleanupPlugin = require('webpack-cleanup-plugin');
8 |
9 | // local css modules
10 | loaders.push({
11 | test: /[\/\\]src[\/\\].*\.css/,
12 | exclude: /(node_modules|bower_components|public)/,
13 | loader: ExtractTextPlugin.extract('style', 'css?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]')
14 | });
15 |
16 | // local scss modules
17 | loaders.push({
18 | test: /[\/\\]src[\/\\].*\.scss/,
19 | exclude: /(node_modules|bower_components|public)/,
20 | loader: ExtractTextPlugin.extract('style', 'css?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!postcss!sass')
21 | });
22 | // global css files
23 | loaders.push({
24 | test: /[\/\\](node_modules|global)[\/\\].*\.css$/,
25 | loader: ExtractTextPlugin.extract('style', 'css')
26 | });
27 |
28 | module.exports = {
29 | entry: [
30 | './src/index.jsx'
31 | ],
32 | output: {
33 | path: path.join(__dirname, 'public'),
34 | filename: '[chunkhash].js'
35 | },
36 | resolve: {
37 | extensions: ['', '.js', '.jsx']
38 | },
39 | module: {
40 | loaders
41 | },
42 | plugins: [
43 | new WebpackCleanupPlugin(),
44 | new webpack.DefinePlugin({
45 | 'process.env': {
46 | NODE_ENV: '"production"'
47 | }
48 | }),
49 | new webpack.optimize.UglifyJsPlugin({
50 | compress: {
51 | warnings: false,
52 | screw_ie8: true,
53 | drop_console: true,
54 | drop_debugger: true
55 | }
56 | }),
57 | new webpack.optimize.OccurenceOrderPlugin(),
58 | new ExtractTextPlugin('[contenthash].css', {
59 | allChunks: true
60 | }),
61 | new HtmlWebpackPlugin({
62 | template: './src/index.html',
63 | title: 'pzgps-reactjs'
64 | }),
65 | new webpack.optimize.DedupePlugin()
66 | ]
67 | };
68 |
--------------------------------------------------------------------------------
/packages/pzgps-server/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /npm-debug.log
3 | /lib/mqkey.js
4 | .DS_Store
5 |
--------------------------------------------------------------------------------
/packages/pzgps-server/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
203 |
--------------------------------------------------------------------------------
/packages/pzgps-server/README.md:
--------------------------------------------------------------------------------
1 | # pzgps-server
2 | The goal of this project is to collect data from the a GPS unit and stream that data out to a web front end via a WebSocket.
3 |
4 | We'll use [NodeJS](https://nodejs.org/en/download/package-manager/#debian-and-ubuntu-based-linux-distributions) and [node-gpsd](https://github.com/eelcocramer/node-gpsd) to read and process the data, make it available via [ws](https://www.npmjs.com/package/ws), and render in the UI with the help of [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API).
5 |
6 | That data, along with user defined information, can then be saved to a [PouchDB database](https://pouchdb.com/guides/databases.html) on your browser/device that syncs to a CouchDB database on your [#pizero](https://www.raspberrypi.org/products/pi-zero/).
7 |
8 | ## Assumptions
9 | You...
10 | * Have a [#pizero](https://www.raspberrypi.org/products/pi-zero/) with an [ARM11](https://en.wikipedia.org/wiki/ARM11) and a GPIO header soldered onto it.
11 | * Have an [Adafruit Ultimate GPS Breakout](https://www.adafruit.com/product/746)
12 | * Have [Raspbian Jessie](https://www.raspberrypi.org/downloads/raspbian/) installed.
13 | * Have [Connected your Adafruit GPS Breakout](https://learn.adafruit.com/adafruit-ultimate-gps-on-the-raspberry-pi/using-uart-instead-of-usb)
14 |
15 | ## Package Structure
16 | * At the root of this package is an `index.js` file, which is a NodeJS application that reads the GPS data and provides it over a WebSocket (on port 9001).
17 | * Sample web apps are in the `/packages/` directory, each with it's own `package.json` file.
18 | - Currently the [Preact](https://preactjs.com/) version of the front end has the most code/features/effort.
19 | - You'll run each part of the project by running `npm start` where the `package.json` is located.
20 | - All front end web apps run on port 9001.
21 | * If you want to persist data to a database, then install CouchDB on your pizero (see below) which will run on port 5984 (the Futon UI would then be at http://yourhostname:5984/_utils/index.html).
22 |
23 | ## Installing NodeJS on the pizero
24 | The version of NodeJS you get via `apt-get install nodejs` is out of date (so you'd be missing some important security patches).
25 |
26 | If you want to compile node from scratch on your [#pizero](https://www.raspberrypi.org/products/pi-zero/) and wait all night for it to complete, then [check out this guide](https://www.youtube.com/watch?v=J6g53Hm0rq4).
27 |
28 | If you want to make things a bit easier, then [download Node](https://nodejs.org/en/download/) using `wget` and install it directly. In this case we'll download the latest version (as of this writing) for ARM on the 6.x branch. Log in to your pi and remain in your home directory...
29 |
30 | wget https://nodejs.org/dist/v6.10.0/node-v6.10.0-linux-armv6l.tar.xz
31 | cd /usr/local
32 | sudo tar --strip-components 1 -xvf ~/node-v6.10.0-linux-armv6l.tar.xz
33 | cd && rm node-v6.10.0-linux-armv6l.tar.xz
34 |
35 | Node is installed now, along with npm.
36 | * `node -v` should yield `v6.10.0`
37 | * `npm -v` should yield `3.10.10`
38 |
39 | Your `/usr/local` dir has a few files left over from the install (ie, CHANGELOG.md, LICENSE, README.md). You can safely remove those.
40 |
41 | Now consider installing [n](https://github.com/tj/n) or [nvm](https://github.com/creationix/nvm) so you can easily install new versions of Node and NPM (and switch between them at will).
42 |
43 | ## Installing CouchDB on the pizero.
44 | [The official PouchDB set up guide is excellent](https://pouchdb.com/guides/setup-couchdb.html). The Preact based front end uses PouchDB to store data locally and to persist data to the CouchDB (see below) instance.
45 |
46 | To install CouchDB on the pizero, log into it, then...
47 |
48 | sudo apt-get install couchdb
49 |
50 |
51 | ## Installing `gpsd`
52 | Log into your pi...
53 |
54 | sudo apt-get install gpsd gpsd-clients python-gps
55 |
56 | Start `gpsd` in verbose/debug mode...
57 |
58 | sudo gpsd /dev/ttyAMA0 -D 2 -n -b -N -P /tmp/gpsd.pid -F /var/run/gpsd.sock
59 |
60 | When starting `gpsd` you might see an error like this...
61 |
62 | gpsd:ERROR: can't bind to local socket /var/run/gpsd.sock
63 |
64 |
65 | You can confirm data is coming to your [#pizero](https://www.raspberrypi.org/products/pi-zero/) with `cat /dev/ttyAMA0` which should show a stream of data. If there is no data from that device, try to `cat /dev/ttyS0` and see if data is streaming from that device, if so, use that device instead wherever you provide the name of a device in a config.
66 |
67 | If you see data coming thru but the command to start `gpsd` failed with an error about not being able to connect, then you might have to disable terminal over serial.
68 |
69 | ### How disable terminal over serial
70 |
71 | * `sudo raspi-config`
72 | * go to `Advanced Options`
73 | * go to `Interfacing Options`
74 | * go to `P6 Serial` and and choose `no`
75 | * `sudo reboot`
76 |
77 | The Adafruit guide mentioned above says you can do this from `/etc/inittab` but that file doesn't exist in Raspbian Jessie (it did in Wheezy). Raspbian Jessie has moved everything to services and there is no `/etc/inittab` file at all, so it's best to use the `raspi-config` command.
78 |
79 | ### Configuring gpsd
80 | To have `gpsd` start up correctly, edit `/etc/default/gpsd`
81 |
82 | # Default settings for the gpsd init script and the hotplug wrapper.
83 |
84 | # Start the gpsd daemon automatically at boot time
85 | START_DAEMON="true"
86 |
87 | # Use USB hotplugging to add new USB devices automatically to the daemon
88 | USBAUTO="false"
89 |
90 | # Devices gpsd should collect to at boot time.
91 | # They need to be read/writeable, either by user gpsd or the group dialout.
92 | DEVICES="/dev/ttyAMA0"
93 |
94 | # Other options you want to pass to gpsd
95 | GPSD_OPTIONS
96 |
97 | GPSD_SOCKET="/var/run/gpsd.sock"
98 |
99 | Then restart: `sudo /etc/init.d/gpsd restart`
100 |
101 | Then try `cgps -s` and you should now see real data. If the GPS Breakout can't see the sky then you might see `no fix` which means it can't see any satellites. Either go outside or put the [#pizero](https://www.raspberrypi.org/products/pi-zero/) on a window sill. 😀
102 |
103 |
104 | ### More useful Commands for dealing with GPSD on the pizero
105 | * `sudo killall gpsd` - To kill gpsd
106 | * `sudo /etc/init.d/gpsd restart` - To elegantly restart gpsd
107 | * `cgps -s` - to open a terminal UI for gps data
108 | * `cat /dev/ttyAMA0` - See raw data from the [Adafruit Ultimate GPS Breakout](https://www.adafruit.com/product/746)
109 |
110 |
111 | ## GPS data via NodeJS
112 | Now that data is coming from the gps unit, thru `gpsd`, we can read that data from node with the help of [node-gpsd](https://github.com/eelcocramer/node-gpsd).
113 |
114 | Run `npm install` to install the deps which includes [node-gpsd](https://github.com/eelcocramer/node-gpsd)
115 |
116 | This will handle the streaming of data from `gpsd` for us and provide the data as JSON (it can also start and stop the daemon, you should read the docs).
117 |
118 | Have a look at the `index.js` in this repo and run `npm start` in your terminal. If everything is set up correctly, you should see some basic info, then a bunch of TPV events streaming by. Now you have something you can write an application around.
119 |
120 | ## Auto Start the WebSocket server at System Boot
121 | After getting everything set up, you might want to have the WebSocket server [auto-start when your pizero boots up](https://www.raspberrypi.org/documentation/linux/usage/rc-local.md).
122 | * Look in the `package.json` file for the `scripts` section
123 | * note the value for the `start` command
124 | * Add that command to `rc.local` with the correct path to the `index.js` file
125 |
126 | Your entry in `rc.local` will look something like this...
127 |
128 | /usr/local/bin/node /home/pi/Projects/pzgps/index.js --port 9000 &
129 |
130 | Change the port number as needed.
131 |
--------------------------------------------------------------------------------
/packages/pzgps-server/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | let argv = require('yargs').argv;
4 | let Server = require('ws').Server;
5 | let merge = require('lodash/merge');
6 | let haversine = require('haversine');
7 |
8 | let daemon = require('./lib/daemon.js');
9 |
10 | let mqkey = {
11 | consumerKey: ''
12 | };
13 |
14 | let location = {
15 | current: {}
16 | };
17 |
18 | if (argv.mq) {
19 | try {
20 | mqkey.consumerKey = require('./lib/mqkey.js').consumerKey;
21 | } catch (err) {
22 | console.warn('Failed to import mqkey', err);
23 | }
24 | }
25 |
26 | let wss = new Server({
27 | port: (argv.port) ? argv.port : '9000'
28 | });
29 |
30 | const dmon = daemon.init({
31 | port: (argv.daemonPort) ? argv.daemonPort : 2947
32 | });
33 | dmon.start();
34 | const listener = daemon.listen({});
35 |
36 | const distance = (from, to) => {
37 | return haversine(from, to);
38 | };
39 |
40 | // set up server listener
41 | wss.on('connection', socket => {
42 | console.log('new websocket connection, (', wss.clients.length, ' total)');
43 |
44 | // send out the location data on an interval
45 | let intervalId = setInterval(function () {
46 | socket.send(JSON.stringify(location.current));
47 | }, 2000);
48 |
49 | socket.on('message', data => { // (data, flags)
50 | let parsedData = JSON.parse(data);
51 |
52 | // there is room for more structure around recieving messages with
53 | // different actions, probably starts to look like a router of some sort
54 | if (parsedData.action === 'pzgps.get.consumerKey' && mqkey.consumerKey) {
55 | socket.send(JSON.stringify(mqkey));
56 | }
57 |
58 | if (parsedData.action === 'pzgps.get.distance') {
59 | let d = distance(parsedData.from, parsedData.to);
60 | socket.send(JSON.stringify(merge(d, {
61 | event: 'pzgps.get.distance'
62 | })));
63 | }
64 | });
65 |
66 | socket.on('close', () => {
67 | clearInterval(intervalId);
68 | console.log('websocket connection closed, (', wss.clients.length, ' remain)');
69 | });
70 | });
71 |
72 | // set up event listeners
73 | listener.on('connected', () => console.log('listener is conected'));
74 | listener.on('DEVICE', data => console.log('device', data));
75 | listener.on('TPV', tpvData => {
76 | location.current = tpvData;
77 | });
78 |
79 | listener.connect();
80 | listener.watch();
81 | listener.device();
82 |
--------------------------------------------------------------------------------
/packages/pzgps-server/lib/daemon.js:
--------------------------------------------------------------------------------
1 | let gpsd = require('node-gpsd');
2 |
3 | let init = opt => {
4 | return new gpsd.Daemon({
5 | program: 'gpsd',
6 | port: (opt.port) ? opt.port : 2947,
7 | device: (opt.dev) ? (opt.dev) : '/dev/ttyAMA0',
8 | pid: (opt.pid) ? opt.pid : '/tmp/gpsd.pid',
9 | logger: {
10 | info: data => {
11 | console.log('daemon info -', data);
12 | },
13 | warn: err => {
14 | console.warn('daemon warn -', err);
15 | },
16 | error: (err, msg) => {
17 | console.error('daemon error -', err, msg);
18 | }
19 | }
20 | });
21 | };
22 |
23 | let startDaemon = daemon => {
24 | daemon.start(function (arg) {
25 | console.log('GPSD start', arg);
26 | });
27 | };
28 |
29 | let stopDaemon = daemon => {
30 | // why doesn't stop() work (gpsd exiting when run via .spawn())
31 | // since it exits, gpsd.js sets it to undefined, but somehow the daemon is still running!
32 | // see: https://github.com/eelcocramer/node-gpsd/blob/master/lib/gpsd.js#L205
33 | daemon.stop(function (arg) {
34 | console.log('GPSD Stop', arg);
35 | });
36 | };
37 |
38 | let listen = opt => {
39 | return new gpsd.Listener({
40 | port: (opt.port) ? opt.port : 2947,
41 | hostname: 'localhost',
42 | parse: true,
43 | logger: {
44 | info: data => {
45 | console.log('listener info -', data);
46 | },
47 | warn: err => {
48 | console.warn('listener warn -', err);
49 | },
50 | error: (err, msg) => {
51 | console.error('listener error -', err, msg);
52 | }
53 | }
54 | });
55 | };
56 |
57 | module.exports = {
58 | init: init,
59 | startDaemon: startDaemon,
60 | stopDaemon: stopDaemon,
61 | listen: listen
62 | };
63 |
--------------------------------------------------------------------------------
/packages/pzgps-server/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "pzgps-server",
3 | "version": "1.1.2",
4 | "description": "Read GPS data from a PiZero in a single page web app via a WebSocket",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "xo",
8 | "start": "node index.js --port 9000",
9 | "withMapquest": "node index.js --port 9000 --mq"
10 | },
11 | "keywords": [
12 | "gps"
13 | ],
14 | "author": "dankapusta",
15 | "license": "Apache-2.0",
16 | "xo": {
17 | "space": true,
18 | "semicolon": true,
19 | "ignores": [
20 | "front-ends/**"
21 | ],
22 | "rules": {
23 | "import/no-dynamic-require": 1
24 | }
25 | },
26 | "dependencies": {
27 | "haversine": "^1.0.2",
28 | "lodash": "^4.17.2",
29 | "node-gpsd": "^0.2.6",
30 | "ws": "^7.2.0",
31 | "yargs": "^6.0.0"
32 | },
33 | "devDependencies": {
34 | "xo": "^0.17.1"
35 | }
36 | }
37 |
--------------------------------------------------------------------------------