├── .DS_Store
├── .gitignore
├── .previews
├── .DS_Store
├── almost.gif
├── full.gif
├── half.gif
├── none.png
├── preview.gif
├── preview_minimal.gif
├── preview_speed.png
├── preview_strength.png
├── preview_strength_fullscreen.png
└── preview_verbose.png
├── LICENSE
├── README.md
├── eslint.config.js
├── images
├── strength_almost.png
├── strength_full.png
├── strength_half.png
└── strength_none.png
├── internet-monitor.css
├── internet-monitor.js
├── node_helper.js
└── package.json
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BrianHepler/internet-monitor/5fd5eb81d19ed1f9b049fb16a4383cb7dbbf2856/.DS_Store
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Node working file
15 | package-lock.json
16 |
17 | # Directory for instrumented libs generated by jscoverage/JSCover
18 | lib-cov
19 |
20 | # Coverage directory used by tools like istanbul
21 | coverage
22 |
23 | # nyc test coverage
24 | .nyc_output
25 |
26 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
27 | .grunt
28 |
29 | # Bower dependency directory (https://bower.io/)
30 | bower_components
31 |
32 | # node-waf configuration
33 | .lock-wscript
34 |
35 | # Compiled binary addons (https://nodejs.org/api/addons.html)
36 | build/Release
37 |
38 | # Dependency directories
39 | node_modules/
40 | jspm_packages/
41 |
42 | # TypeScript v1 declaration files
43 | typings/
44 |
45 | # Optional npm cache directory
46 | .npm
47 |
48 | # Optional eslint cache
49 | .eslintcache
50 |
51 | # Optional REPL history
52 | .node_repl_history
53 |
54 | # Output of 'npm pack'
55 | *.tgz
56 |
57 | # Yarn Integrity file
58 | .yarn-integrity
59 |
60 | # dotenv environment variables file
61 | .env
62 |
63 | # next.js build output
64 | .next
65 |
--------------------------------------------------------------------------------
/.previews/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BrianHepler/internet-monitor/5fd5eb81d19ed1f9b049fb16a4383cb7dbbf2856/.previews/.DS_Store
--------------------------------------------------------------------------------
/.previews/almost.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BrianHepler/internet-monitor/5fd5eb81d19ed1f9b049fb16a4383cb7dbbf2856/.previews/almost.gif
--------------------------------------------------------------------------------
/.previews/full.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BrianHepler/internet-monitor/5fd5eb81d19ed1f9b049fb16a4383cb7dbbf2856/.previews/full.gif
--------------------------------------------------------------------------------
/.previews/half.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BrianHepler/internet-monitor/5fd5eb81d19ed1f9b049fb16a4383cb7dbbf2856/.previews/half.gif
--------------------------------------------------------------------------------
/.previews/none.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BrianHepler/internet-monitor/5fd5eb81d19ed1f9b049fb16a4383cb7dbbf2856/.previews/none.png
--------------------------------------------------------------------------------
/.previews/preview.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BrianHepler/internet-monitor/5fd5eb81d19ed1f9b049fb16a4383cb7dbbf2856/.previews/preview.gif
--------------------------------------------------------------------------------
/.previews/preview_minimal.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BrianHepler/internet-monitor/5fd5eb81d19ed1f9b049fb16a4383cb7dbbf2856/.previews/preview_minimal.gif
--------------------------------------------------------------------------------
/.previews/preview_speed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BrianHepler/internet-monitor/5fd5eb81d19ed1f9b049fb16a4383cb7dbbf2856/.previews/preview_speed.png
--------------------------------------------------------------------------------
/.previews/preview_strength.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BrianHepler/internet-monitor/5fd5eb81d19ed1f9b049fb16a4383cb7dbbf2856/.previews/preview_strength.png
--------------------------------------------------------------------------------
/.previews/preview_strength_fullscreen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BrianHepler/internet-monitor/5fd5eb81d19ed1f9b049fb16a4383cb7dbbf2856/.previews/preview_strength_fullscreen.png
--------------------------------------------------------------------------------
/.previews/preview_verbose.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BrianHepler/internet-monitor/5fd5eb81d19ed1f9b049fb16a4383cb7dbbf2856/.previews/preview_verbose.png
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 ronny3050
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # internet-monitor
2 |
3 | A [MagicMirror²](https://github.com/MagicMirrorOrg/MagicMirror) module to monitor internet statistics such as strength and speed information.
4 |
5 | **This is a fork of ronny3050's module with some modifications to get it working again.**
6 |
7 | 
8 | 
9 | 
10 |
11 | ## Installation
12 |
13 | To install the module, just clone this repository to your **modules** folder:
14 |
15 | `git clone https://github.com/BrianHepler/internet-monitor`.
16 |
17 | Then run `cd internet-monitor` and `npm install` which will install the dependencies.
18 |
19 | ## Using the module
20 |
21 | To use this module, add it to the modules array in the `config/config.js` file:
22 |
23 | ````javascript
24 | modules: [
25 | {
26 | module: 'internet-monitor',
27 | position: 'top_center',
28 | header: 'Internet Monitor',
29 | config:{
30 | type: '',
31 | maxTime: 20000,
32 | updateInterval: 0,
33 | verbose: false,
34 | serverId: 54504,
35 | displayStrength: true,
36 | displaySpeed: true,
37 | strengthIconSize: 80,
38 | maxGaugeScale: 100,
39 | },
40 | }
41 | ]
42 | ````
43 |
44 | You can also customize the wifi symbol.
45 |
46 | ````javascript
47 | modules: [
48 | {
49 | module: 'internet-monitor',
50 | position: 'top_center',
51 | header: 'Internet Monitor',
52 | config:{
53 | type: '',
54 | maxTime: 20000,
55 | updateInterval: 0,
56 | verbose: false,
57 | displayStrength: true,
58 | displaySpeed: true,
59 | strengthIconSize: 80,
60 | maxGaugeScale: 100,
61 | wifiSymbol:{
62 | size: 50,
63 | fullColor: '#3afc25',
64 | almostColor: '#ffff0c',
65 | halfColor: '#ff8c00',
66 | noneColor: '#ff1111'
67 | },
68 | },
69 | }
70 | ]
71 | ````
72 |
73 | ## Configuration options
74 |
75 | The following properties can be configured:
76 |
77 | | Option | Description |
78 | |--------|--------------|
79 | |type | Style of the speed gauges
Possible values: 'minimal'
Minimalistic Style as shown in the second image above.
Default value: ''
|
80 | | updateInterval | Time to rerun/update tests (Milliseconds)
Default value: 0
Please note that updateInterval
has to be greater than maxTime
|
81 | | displayStrength | Display Internet Strength
Possible values: true
or false
Default value: true
|
82 | | displaySpeed | Display download and upload speed gauges
Possible values: true
or false
Default value: true
|
83 | | strengthIconSize | Size of the strength icon
Default value: 80
|
84 | | maxGuageScale | Maximum gauge value (Mbps)
Default value: 100
|
85 | | serverId | Test against specific SpeedTest server (optional)
Default value: ''
List of servers can be found at SpeedTest. |
86 | | wifiSymbol | Customize WiFi Symbol (Optional)
size
Size of the WiFi SymbolfullColor
Hex color code for full strength 
almostColor
Hex color code for almost strength 
halfColor
Hex color code for half strength 
noneColor
Hex color code for 0 strength 
|
87 |
--------------------------------------------------------------------------------
/eslint.config.js:
--------------------------------------------------------------------------------
1 | const globals = require("globals");
2 | const {configs: eslintConfigs} = require("@eslint/js");
3 | const eslintPluginImport = require("eslint-plugin-import");
4 | const eslintPluginStylistic = require("@stylistic/eslint-plugin");
5 |
6 | const config = [
7 | {
8 | files: ["**/*.js"],
9 | languageOptions: {
10 | globals: {
11 | ...globals.browser,
12 | ...globals.node
13 | }
14 | },
15 | plugins: {
16 | ...eslintPluginStylistic.configs["all-flat"].plugins,
17 | import: eslintPluginImport
18 | },
19 | rules: {
20 | ...eslintConfigs.all.rules,
21 | ...eslintPluginImport.configs.recommended.rules,
22 | ...eslintPluginStylistic.configs["all-flat"].rules,
23 | "capitalized-comments": "off",
24 | complexity: ["error", 25],
25 | "consistent-this": "off",
26 | "default-case": "off",
27 | "func-style": "off",
28 | "init-declarations": "off",
29 | "line-comment-position": "off",
30 | "max-lines": "off",
31 | "max-lines-per-function": ["error", 110],
32 | "max-params": "off",
33 | "max-statements": ["error", 50],
34 | "multiline-comment-style": "off",
35 | "no-await-in-loop": "off",
36 | "no-inline-comments": "off",
37 | "no-magic-numbers": "off",
38 | "no-undef": "warn",
39 | "no-ternary": "off",
40 | "one-var": "off",
41 | "sort-keys": "off",
42 | strict: "off",
43 | "@stylistic/array-element-newline": ["error", "consistent"],
44 | "@stylistic/dot-location": ["error", "property"],
45 | "@stylistic/function-call-argument-newline": ["error", "consistent"],
46 | "@stylistic/indent": ["error", 2],
47 | "@stylistic/lines-around-comment": "off",
48 | "@stylistic/object-property-newline": "off",
49 | "@stylistic/quote-props": ["error", "as-needed"],
50 | "@stylistic/padded-blocks": ["error", "never"]
51 | }
52 | },
53 | {
54 | files: ["**/*.mjs"],
55 | languageOptions: {
56 | globals: {
57 | ...globals.node
58 | },
59 | sourceType: "module"
60 | },
61 | plugins: {
62 | ...eslintPluginStylistic.configs["all-flat"].plugins
63 | },
64 | rules: {
65 | ...eslintConfigs.all.rules,
66 | ...eslintPluginStylistic.configs["all-flat"].rules,
67 | "func-style": "off",
68 | "max-lines-per-function": ["error", 100],
69 | "no-magic-numbers": "off",
70 | "one-var": "off",
71 | "prefer-destructuring": "off"
72 | }
73 | }
74 | ];
75 |
76 | /*
77 | * Set debug to true for testing purposes.
78 | * Since some plugins have not yet been optimized for the flat config,
79 | * we will be able to optimize this file in the future. It can be helpful
80 | * to write the ESLint config to a file and compare it after changes.
81 | */
82 | const debug = false;
83 |
84 | if (debug === true) {
85 | const FileSystem = require("fs");
86 | FileSystem.writeFile("eslint-config-DEBUG.json", JSON.stringify(config, null, 2), (error) => {
87 | if (error) {
88 | throw error;
89 | }
90 | });
91 | }
92 |
93 | module.exports = config;
94 |
--------------------------------------------------------------------------------
/images/strength_almost.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BrianHepler/internet-monitor/5fd5eb81d19ed1f9b049fb16a4383cb7dbbf2856/images/strength_almost.png
--------------------------------------------------------------------------------
/images/strength_full.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BrianHepler/internet-monitor/5fd5eb81d19ed1f9b049fb16a4383cb7dbbf2856/images/strength_full.png
--------------------------------------------------------------------------------
/images/strength_half.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BrianHepler/internet-monitor/5fd5eb81d19ed1f9b049fb16a4383cb7dbbf2856/images/strength_half.png
--------------------------------------------------------------------------------
/images/strength_none.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BrianHepler/internet-monitor/5fd5eb81d19ed1f9b049fb16a4383cb7dbbf2856/images/strength_none.png
--------------------------------------------------------------------------------
/internet-monitor.css:
--------------------------------------------------------------------------------
1 | #downloadSpeedGauge, #uploadSpeedGauge{
2 | width:200px; height:160px;
3 | display: inline-block;
4 | margin: 1em;
5 | }
6 |
7 | .wifi{
8 | z-index : 1;
9 | }
10 | .wifi-symbol-1 {
11 | display: none;
12 | }
13 | .wifi-symbol-1 [foo], .wifi-symbol-1 {
14 | display: block;
15 | position: absolute;
16 | top: 65%;
17 | display: inline-block;
18 | width: 150px;
19 | height: 150px;
20 | margin-top: -187.5px;
21 | -ms-transform: rotate(-45deg) translate(-100px);
22 | -moz-transform: rotate(-45deg) translate(-100px);
23 | -o-transform: rotate(-45deg) translate(-100px);
24 | -webkit-transform: rotate(-45deg) translate(-100px);
25 | transform: rotate(-45deg) translate(-100px);
26 | }
27 | .wifi-symbol-1 .wifi-circle {
28 | box-sizing: border-box;
29 | -moz-box-sizing: border-box;
30 | display: block;
31 | width: 100%;
32 | height: 100%;
33 | font-size: 21.42857px;
34 | position: absolute;
35 | bottom: 0;
36 | left: 0;
37 | border-color: #FFFFCC;
38 | border-style: solid;
39 | border-width: 1em 1em 0 0;
40 | -webkit-border-radius: 0 100% 0 0;
41 | border-radius: 0 100% 0 0;
42 | opacity: 0;
43 | -o-animation: wifianimation-2 3s infinite;
44 | -moz-animation: wifianimation-2 3s infinite;
45 | -webkit-animation: wifianimation-2 3s infinite;
46 | animation: wifianimation-2 3s infinite;
47 | }
48 | .wifi-symbol-1 .wifi-circle.first {
49 | -o-animation-delay: 800ms;
50 | -moz-animation-delay: 800ms;
51 | -webkit-animation-delay: 800ms;
52 | animation-delay: 800ms;
53 | }
54 | .wifi-symbol-1 .wifi-circle.second {
55 | width: 5em;
56 | height: 5em;
57 | -o-animation-delay: 400ms;
58 | -moz-animation-delay: 400ms;
59 | -webkit-animation-delay: 400ms;
60 | animation-delay: 400ms;
61 | }
62 | .wifi-symbol-1 .wifi-circle.third {
63 | width: 3em;
64 | height: 3em;
65 | }
66 | .wifi-symbol-1 .wifi-circle.fourth {
67 | width: 1em;
68 | height: 1em;
69 | opacity: 1;
70 | background-color: #FFFFCC;
71 | -o-animation: none;
72 | -moz-animation: none;
73 | -webkit-animation: none;
74 | animation: none;
75 | }
76 |
77 | .wifi-symbol-2 {
78 | display: none;
79 | }
80 | .wifi-symbol-2 [foo], .wifi-symbol-2 {
81 | display: block;
82 | position: absolute;
83 | top: 65%;
84 | display: inline-block;
85 | width: 150px;
86 | height: 150px;
87 | margin-top: -187.5px;
88 | -ms-transform: rotate(-45deg) translate(-100px);
89 | -moz-transform: rotate(-45deg) translate(-100px);
90 | -o-transform: rotate(-45deg) translate(-100px);
91 | -webkit-transform: rotate(-45deg) translate(-100px);
92 | transform: rotate(-45deg) translate(-100px);
93 | }
94 | .wifi-symbol-2 .wifi-circle {
95 | box-sizing: border-box;
96 | -moz-box-sizing: border-box;
97 | display: block;
98 | width: 100%;
99 | height: 100%;
100 | font-size: 21.42857px;
101 | position: absolute;
102 | bottom: 0;
103 | left: 0;
104 | border-color: #FFFF0C;
105 | border-style: solid;
106 | border-width: 1em 1em 0 0;
107 | -webkit-border-radius: 0 100% 0 0;
108 | border-radius: 0 100% 0 0;
109 | opacity: 0;
110 | -o-animation: wifianimation-2 3s infinite;
111 | -moz-animation: wifianimation-2 3s infinite;
112 | -webkit-animation: wifianimation-2 3s infinite;
113 | animation: wifianimation-2 3s infinite;
114 | }
115 | .wifi-symbol-2 .wifi-circle.first {
116 | opacity: 0.3;
117 | -o-animation: none;
118 | -moz-animation: none;
119 | -webkit-animation: none;
120 | animation: none;
121 | }
122 | .wifi-symbol-2 .wifi-circle.second {
123 | width: 5em;
124 | height: 5em;
125 | -o-animation-delay: 400ms;
126 | -moz-animation-delay: 400ms;
127 | -webkit-animation-delay: 400ms;
128 | animation-delay: 400ms;
129 | }
130 | .wifi-symbol-2 .wifi-circle.third {
131 | width: 3em;
132 | height: 3em;
133 | }
134 | .wifi-symbol-2 .wifi-circle.fourth {
135 | width: 1em;
136 | height: 1em;
137 | opacity: 1;
138 | background-color: #FFFF0C;
139 | -o-animation: none;
140 | -moz-animation: none;
141 | -webkit-animation: none;
142 | animation: none;
143 | }
144 |
145 | .wifi-symbol-3 {
146 | display: none;
147 | }
148 | .wifi-symbol-3 [foo], .wifi-symbol-3 {
149 | display: block;
150 | position: absolute;
151 | top: 65%;
152 | display: inline-block;
153 | width: 150px;
154 | height: 150px;
155 | margin-top: -187.5px;
156 | -ms-transform: rotate(-45deg) translate(-100px);
157 | -moz-transform: rotate(-45deg) translate(-100px);
158 | -o-transform: rotate(-45deg) translate(-100px);
159 | -webkit-transform: rotate(-45deg) translate(-100px);
160 | transform: rotate(-45deg) translate(-100px);
161 | }
162 | .wifi-symbol-3 .wifi-circle {
163 | box-sizing: border-box;
164 | -moz-box-sizing: border-box;
165 | display: block;
166 | width: 100%;
167 | height: 100%;
168 | font-size: 21.42857px;
169 | position: absolute;
170 | bottom: 0;
171 | left: 0;
172 | border-color: #FFFF0C;
173 | border-style: solid;
174 | border-width: 1em 1em 0 0;
175 | -webkit-border-radius: 0 100% 0 0;
176 | border-radius: 0 100% 0 0;
177 | opacity: 0;
178 | -o-animation: wifianimation-2 3s infinite;
179 | -moz-animation: wifianimation-2 3s infinite;
180 | -webkit-animation: wifianimation-2 3s infinite;
181 | animation: wifianimation-2 3s infinite;
182 | }
183 | .wifi-symbol-3 .wifi-circle.first {
184 | opacity: 0.3;
185 | -o-animation: none;
186 | -moz-animation: none;
187 | -webkit-animation: none;
188 | animation: none;
189 | }
190 | .wifi-symbol-3 .wifi-circle.second {
191 | width: 5em;
192 | height: 5em;
193 | opacity: 0.3;
194 | -o-animation: none;
195 | -moz-animation: none;
196 | -webkit-animation: none;
197 | animation: none;
198 | }
199 | .wifi-symbol-3 .wifi-circle.third {
200 | width: 3em;
201 | height: 3em;
202 | }
203 | .wifi-symbol-3 .wifi-circle.fourth {
204 | width: 1em;
205 | height: 1em;
206 | opacity: 1;
207 | background-color: #FFFF0C;
208 | -o-animation: none;
209 | -moz-animation: none;
210 | -webkit-animation: none;
211 | animation: none;
212 | }
213 |
214 | .wifi-symbol-4 {
215 | display: none;
216 | }
217 | .wifi-symbol-4 [foo], .wifi-symbol-4 {
218 | display: block;
219 | position: absolute;
220 | top: 65%;
221 | display: inline-block;
222 | width: 150px;
223 | height: 150px;
224 | margin-top: -187.5px;
225 | -ms-transform: rotate(-45deg) translate(-100px);
226 | -moz-transform: rotate(-45deg) translate(-100px);
227 | -o-transform: rotate(-45deg) translate(-100px);
228 | -webkit-transform: rotate(-45deg) translate(-100px);
229 | transform: rotate(-45deg) translate(-100px);
230 | }
231 | .wifi-symbol-4 .wifi-circle {
232 | box-sizing: border-box;
233 | -moz-box-sizing: border-box;
234 | display: block;
235 | width: 100%;
236 | height: 100%;
237 | font-size: 21.42857px;
238 | position: absolute;
239 | bottom: 0;
240 | left: 0;
241 | border-color: #FFFF0C;
242 | border-style: solid;
243 | border-width: 1em 1em 0 0;
244 | -webkit-border-radius: 0 100% 0 0;
245 | border-radius: 0 100% 0 0;
246 | opacity: 0;
247 | -o-animation: wifianimation-2 3s infinite;
248 | -moz-animation: wifianimation-2 3s infinite;
249 | -webkit-animation: wifianimation-2 3s infinite;
250 | animation: wifianimation-2 3s infinite;
251 | }
252 | .wifi-symbol-4 .wifi-circle.first {
253 | opacity: 0.3;
254 | -o-animation: none;
255 | -moz-animation: none;
256 | -webkit-animation: none;
257 | animation: none;
258 | }
259 | .wifi-symbol-4 .wifi-circle.second {
260 | width: 5em;
261 | height: 5em;
262 | opacity: 0.3;
263 | -o-animation: none;
264 | -moz-animation: none;
265 | -webkit-animation: none;
266 | animation: none;
267 | }
268 | .wifi-symbol-4 .wifi-circle.third {
269 | width: 3em;
270 | height: 3em;
271 | opacity: 0.3;
272 | -o-animation: none;
273 | -moz-animation: none;
274 | -webkit-animation: none;
275 | animation: none;
276 | }
277 | .wifi-symbol-4 .wifi-circle.fourth {
278 | width: 1em;
279 | height: 1em;
280 | opacity: 1;
281 | background-color: #FFFF0C;
282 | -o-animation: none;
283 | -moz-animation: none;
284 | -webkit-animation: none;
285 | animation: none;
286 | }
287 |
288 | @-o-keyframes wifianimation-2 {
289 | 0% {
290 | opacity: 1;
291 | }
292 | 5% {
293 | opactiy: 0.8;
294 | }
295 | 6% {
296 | opactiy: 0.9;
297 | }
298 | 100% {
299 | opactiy: 0.1;
300 | }
301 | }
302 | @-moz-keyframes wifianimation-2 {
303 | 0% {
304 | opacity: 1;
305 | }
306 | 5% {
307 | opactiy: 0.8;
308 | }
309 | 6% {
310 | opactiy: 0.9;
311 | }
312 | 100% {
313 | opactiy: 0.1;
314 | }
315 | }
316 | @-webkit-keyframes wifianimation-2 {
317 | 0% {
318 | opacity: 1;
319 | }
320 | 5% {
321 | opactiy: 0.8;
322 | }
323 | 6% {
324 | opactiy: 0.9;
325 | }
326 | 100% {
327 | opactiy: 0.1;
328 | }
329 | }
--------------------------------------------------------------------------------
/internet-monitor.js:
--------------------------------------------------------------------------------
1 | /* global JustGage Module Log $ */
2 | /**
3 | * Created by debayan on 7/24/16.
4 | */
5 |
6 | Module.register("internet-monitor", {
7 |
8 | defaults: {
9 | serverId: "",
10 | type: "",
11 | updateInterval: 60 * 1000 * 30,
12 | verbose: false,
13 | displayStrength: true,
14 | displaySpeed: true,
15 | strengthIconSize: 80,
16 | maxGaugeScale: 100
17 | },
18 | payload: [],
19 |
20 | downloadBarState: "not_started",
21 | updating: false,
22 |
23 | start () {
24 | Log.log("Internet-monitor module started!");
25 | this.sendSocketNotification("Start", this.config);
26 | },
27 |
28 | getScripts () {
29 | return [
30 | this.file("node_modules/justgage/raphael.min.js"),
31 | this.file("node_modules/justgage/dist/justgage.min.js"),
32 | this.file("node_modules/jquery/dist/jquery.min.js")
33 | ];
34 | },
35 |
36 | getStyles () {
37 | return ["internet-monitor.css"];
38 | },
39 |
40 | notificationReceived (notification, payload, sender) {
41 | // Module is ready. Start the initial check
42 | if (notification === "MODULE_DOM_CREATED") {
43 | this.sendSocketNotification("Check", this.config);
44 | }
45 | Log.debug(`notificationReceived - payload: ${payload}`);
46 | Log.debug(`notificationReceived - sender: ${sender}`);
47 | },
48 |
49 | socketNotificationReceived (notification, payload) {
50 | if (notification === "downloadSpeedProgress") {
51 | if (this.config.displaySpeed) {
52 | if (this.downloadBarState === "not_started") {
53 | this.downloadBarState = "started";
54 | }
55 | Log.log("updating DOWNLOAD");
56 | this.download.refresh(payload, this.config.maxGaugeScale);
57 | }
58 | }
59 | if (notification === "uploadSpeedProgress") {
60 | if (this.config.displaySpeed) {
61 | Log.log("updating UPLOAD");
62 | this.upload.refresh(payload, this.config.maxGaugeScale);
63 | }
64 | }
65 | let container;
66 | if (notification === "data") {
67 | if (this.config.verbose) {
68 | if (!this.updating) {
69 | container = document.createElement("div");
70 | container.style = "text-align: left; display:inline-block;";
71 | $(container).appendTo("#internetData");
72 | }
73 | $("#internetData > div").html(` Server: ${payload.server.host}`)
74 | .append("
" +
75 | ` Location: ${payload.server.location} (${payload.server.country})`)
76 | .append("
");
77 | }
78 | }
79 |
80 | if (notification === "ping") {
81 | // Log.log("ping [" + payload + "]");
82 | // if (this.downloadBarState == "not_started") {
83 | // this.updateDom();
84 | // }
85 |
86 | if (this.config.displayStrength) {
87 | if (Object.hasOwn(this.config, "wifiSymbol")) {
88 | if (payload < 70) {
89 | $(container).append("");
90 | } else if (payload >= 70 && payload < 100) {
91 | $(container).append("");
92 | } else if (payload >= 100 && payload < 150) {
93 | $(container).append("");
94 | } else if (payload >= 150) {
95 | $(container).append("");
96 | }
97 |
98 | $(".wifi-symbol-1 .wifi-circle").css({
99 | "border-color": this.config.wifiSymbol.fullColor,
100 | "font-size": this.config.wifiSymbol.size / 7,
101 | "margin-top": 0 - this.config.wifiSymbol.size - this.config.wifiSymbol.size * 0.25,
102 | "margin-left": 0.5 * (150 - this.config.wifiSymbol.size)
103 | });
104 | $(".wifi-symbol-1 [foo], .wifi-symbol-1").css({
105 | width: this.config.wifiSymbol.size,
106 | height: this.config.wifiSymbol.size
107 | });
108 |
109 | $(".wifi-symbol-2 .wifi-circle").css({
110 | "border-color": this.config.wifiSymbol.almostColor,
111 | "font-size": this.config.wifiSymbol.size / 7,
112 | "margin-top": 0 - this.config.wifiSymbol.size - this.config.wifiSymbol.size * 0.25,
113 | "margin-left": 0.5 * (150 - this.config.wifiSymbol.size)
114 | });
115 | $(".wifi-symbol-2 [foo], .wifi-symbol-2").css({
116 | width: this.config.wifiSymbol.size,
117 | height: this.config.wifiSymbol.size
118 | });
119 |
120 | $(".wifi-symbol-3 .wifi-circle").css({
121 | "border-color": this.config.wifiSymbol.halfColor,
122 | "font-size": this.config.wifiSymbol.size / 7,
123 | "margin-top": 0 - this.config.wifiSymbol.size - this.config.wifiSymbol.size * 0.25,
124 | "margin-left": 0.5 * (150 - this.config.wifiSymbol.size)
125 | });
126 | $(".wifi-symbol-3 [foo], .wifi-symbol-3").css({
127 | width: this.config.wifiSymbol.size,
128 | height: this.config.wifiSymbol.size
129 | });
130 |
131 | $(".wifi-symbol-4 .wifi-circle").css({
132 | "border-color": this.config.wifiSymbol.noneColor,
133 | "font-size": this.config.wifiSymbol.size / 7,
134 | "margin-top": 0 - this.config.wifiSymbol.size - this.config.wifiSymbol.size * 0.25,
135 | "margin-left": 0.5 * (150 - this.config.wifiSymbol.size)
136 | });
137 | $(".wifi-symbol-4 [foo], .wifi-symbol-4").css({
138 | width: this.config.wifiSymbol.size,
139 | height: this.config.wifiSymbol.size
140 | });
141 | } else if (payload < 70) {
142 | $("#pingStrength").attr("src", this.file("images/strength_full.png"));
143 | } else if (payload >= 70 && payload < 100) {
144 | $("#pingStrength").attr("src", this.file("images/strength_almost.png"));
145 | } else if (payload >= 100 && payload < 150) {
146 | $("#pingStrength").attr("src", this.file("images/strength_half.png"));
147 | } else if (payload >= 150) {
148 | $("#pingStrength").attr("src", this.file("images/strength_none.png"));
149 | }
150 | }
151 | }
152 | },
153 |
154 | getDom () {
155 | const wrapper = document.createElement("div");
156 | wrapper.className = "small";
157 | // Log.log(this.config);
158 |
159 | if (this.config.displayStrength) {
160 | Log.log("creating pingDiv");
161 | const pingDiv = document.createElement("div");
162 | pingDiv.id = "pingDiv";
163 | pingDiv.className = "strength";
164 |
165 | const img = document.createElement("img");
166 | img.src = this.file("images/strength_none.png");
167 | img.height = this.config.strengthIconSize;
168 | img.id = "pingStrength";
169 | img.className = "pingStrength";
170 | pingDiv.appendChild(img);
171 |
172 | wrapper.appendChild(pingDiv);
173 | }
174 |
175 | if (this.config.displaySpeed) {
176 | Log.log("creating speed");
177 | const minimal = this.config.type === "minimal";
178 |
179 | const downloadSpeedGauge = document.createElement("div");
180 | downloadSpeedGauge.id = "downloadSpeedGauge";
181 | downloadSpeedGauge.className = "speedGauge";
182 |
183 | const uploadSpeedGauge = document.createElement("div");
184 | uploadSpeedGauge.id = "uploadSpeedGauge";
185 | uploadSpeedGauge.className = "speedGauge";
186 |
187 | this.download = new JustGage({
188 | // id: "downloadSpeedGauge",
189 | parentNode: downloadSpeedGauge,
190 | value: 0,
191 | min: 0,
192 | max: this.config.maxGaugeScale,
193 | title: "Download Speed",
194 | refreshAnimationType: "linear",
195 | gaugeWidthScale: 0.8,
196 | valueFontColor: "#FFFFFF",
197 | valueFontFamily: "Roboto Condensed",
198 | titleFontFamily: "Roboto Condensed",
199 | titleFontColor: "#AAAAAA",
200 | hideMindMax: minimal,
201 | gaugeColor: "#000000",
202 | levelColors: ["#FF0000", "#FFFF00", "#00FF00"],
203 | hideInnerShadow: true,
204 | symbol: "Mbps"
205 | });
206 |
207 | this.upload = new JustGage({
208 | // id: "uploadSpeedGauge",
209 | parentNode: uploadSpeedGauge,
210 | value: 0,
211 | min: 0,
212 | max: this.config.maxGaugeScale,
213 | title: "Upload Speed",
214 | refreshAnimationType: "linear",
215 | gaugeWidthScale: 0.8,
216 | valueFontColor: "#FFFFFF",
217 | valueFontFamily: "Roboto Condensed",
218 | titleFontFamily: "Roboto Condensed",
219 | titleFontColor: "#AAAAAA",
220 | hideMindMax: minimal,
221 | gaugeColor: "#000000",
222 | levelColors: ["#FF0000", "#FFFF00", "#00FF00"],
223 | hideInnerShadow: true,
224 | symbol: "Mbps"
225 | });
226 |
227 | if (minimal) {
228 | const downOpt = {
229 | gaugeColor: "#000",
230 | levelColors: "#fff",
231 | hideInnerShadow: true
232 | };
233 | const upOpt = {
234 | gaugeColor: "#000",
235 | levelColors: "#fff",
236 | hideInnerShadow: true
237 | };
238 | this.download.update(downOpt);
239 | this.upload.update(upOpt);
240 | }
241 | wrapper.appendChild(downloadSpeedGauge);
242 | wrapper.appendChild(uploadSpeedGauge);
243 | }
244 |
245 | if (this.config.verbose) {
246 | const data = document.createElement("div");
247 | data.id = "internetData";
248 | wrapper.appendChild(data);
249 | }
250 |
251 | return wrapper;
252 | }
253 |
254 | });
255 |
--------------------------------------------------------------------------------
/node_helper.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by debayan on 7/23/16.
3 | */
4 | const Log = require("logger");
5 | const NodeHelper = require("node_helper");
6 | const speedtest = require("speedtest-net");
7 |
8 | module.exports = NodeHelper.create({
9 | start () {
10 | Log.log(`${this.name} helper started ...`);
11 | this.config = null;
12 | this.interval = null;
13 | },
14 |
15 | socketNotificationReceived (notification, payload) {
16 | if (notification === "Start") {
17 | this.config = payload;
18 | }
19 | if (notification === "Check") {
20 | this.checkSpeed();
21 | }
22 | },
23 |
24 | async checkSpeed () {
25 | Log.log("Checking speed...");
26 | let Check;
27 | try {
28 | Check = await speedtest({serverId: this.config.serverId,
29 | acceptLicense: true,
30 | acceptGdpr: true,
31 | progress: (data) => this.handleProgressEvent(data)});
32 | } catch (err) {
33 | Log.error("[internet-monitor]", err.message);
34 | } finally {
35 | if (Check) {
36 | Log.debug("Result: ", Check);
37 | this.sendSocketNotification("data", Check);
38 | Log.debug("Done");
39 | }
40 | } // end try
41 | this.scheduleUpdate();
42 | },
43 |
44 | handleProgressEvent (data) {
45 | switch (data.type) {
46 | case "download":
47 | Log.debug(`Examining download statistic: ${data.download.bandwidth}`);
48 | this.sendSocketNotification("downloadSpeedProgress", this.oToMbps(data.download.bandwidth));
49 | break;
50 | case "upload":
51 | Log.debug(`Examining upload statistic: ${data.upload.bandwidth}`);
52 | this.sendSocketNotification("uploadSpeedProgress", this.oToMbps(data.upload.bandwidth));
53 | break;
54 | case "ping":
55 | Log.debug(`Examining ping statistic:${data.ping.latency}`);
56 | this.sendSocketNotification("ping", Math.round(data.ping.latency));
57 | }
58 | },
59 |
60 | // Convert octect to Mbps [Match with Speedtest web result]
61 | oToMbps (value) {
62 | if (!value) {
63 | return 0;
64 | }
65 | return (value * 0.000008).toFixed(2);
66 | },
67 |
68 | /** update process **/
69 | scheduleUpdate () {
70 | if (this.config.updateInterval < 60 * 1000) {
71 | this.config.updateInterval = 60 * 1000;
72 | }
73 | clearInterval(this.interval);
74 | this.interval = setInterval(() => this.checkSpeed(), this.config.updateInterval);
75 | }
76 |
77 | });
78 |
79 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "internet-speed",
3 | "version": "2.0.0",
4 | "description": "Displays ping, download and upload speed on your smart mirror.",
5 | "repository": {
6 | "type": "git",
7 | "url": "https://github.com/BrianHepler/internet-monitor"
8 | },
9 | "main": "index.js",
10 | "scripts": {
11 | "lint": "eslint .",
12 | "lint:fix": "eslint . --fix",
13 | "test": "npm run lint"
14 | },
15 | "keywords": [
16 | "internet",
17 | "speed"
18 | ],
19 | "author": "Debayan Deb",
20 | "license": "MIT",
21 | "dependencies": {
22 | "speedtest-net": "flying19880517/speedtest.net",
23 | "jquery": "^3.7.1",
24 | "justgage": "^1.6.1"
25 | },
26 | "devDependencies": {
27 | "@eslint/js": "^8.56.0",
28 | "@stylistic/eslint-plugin": "^1.5.3",
29 | "eslint": "^8.56.0",
30 | "eslint-plugin-import": "^2.29.1",
31 | "globals": "^13.24.0"
32 | }
33 | }
34 |
--------------------------------------------------------------------------------