├── .gitignore ├── CNAME ├── LICENSE ├── README.md └── app ├── adafruit.html ├── favicon.svg ├── index.html ├── iot-debugger-icon.svg ├── styles.css └── thingspeak.html /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_STORE 2 | .vscode -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | iot-debugger.nothans.com -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016-2024 Hans Scharler 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 | # IoT Debugger 2 | Use this web-based tool to see data stored in an Internet of Things data service such as [ThingSpeak](https://thingspeak.com/channels/9). 3 | 4 | ## Demo 5 | * [Open Demo App for ThingSpeak](https://iot-debugger.nothans.com/app/index.html) 6 | * Click play button to start getting data 7 | 8 | ## How to Use IoT Debugger 9 | * Download project 10 | * Open index.html in a browser tab 11 | * Select ThingSpeak 12 | * To use ThingSpeak - Enter the ThingSpeak Channel and Read API Key and click the play button to start getting data 13 | -------------------------------------------------------------------------------- /app/adafruit.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | IoT Debugger - Adafruit IO 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 240 | 241 | 242 |
243 | 256 | 257 |
258 |
259 |
260 | 261 |
262 |

Adafruit IO Feed Data

263 |
264 | 265 |
266 |
267 | 268 | 269 |
270 |
271 | 272 |
273 |
274 | 275 | 276 |
277 |
278 | 279 |
280 |
281 | 282 | 283 |
284 |
285 | 286 |
287 |
288 | 289 | 290 |
291 |
292 | 293 |
294 | 297 |
298 |
299 |
300 | 301 | 302 |
303 | 304 |

305 |

Feed Data

306 |
307 | 308 | 309 |
310 |
311 |
312 |
313 |
314 |
315 | 316 | 324 |
325 | 326 | 327 | -------------------------------------------------------------------------------- /app/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | IoT Debugger - Home 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 42 | 43 |
44 |
45 | 69 |
70 |
71 | 72 | 80 |
81 | 82 | -------------------------------------------------------------------------------- /app/iot-debugger-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /app/styles.css: -------------------------------------------------------------------------------- 1 | .mdl-layout__header-row { 2 | padding-left: 40px; 3 | } 4 | .page-content { 5 | padding: 24px; 6 | max-width: 800px; 7 | margin: 0 auto; 8 | } 9 | .welcome-card { 10 | width: 100%; 11 | min-height: 0; 12 | } 13 | .welcome-card > .mdl-card__title { 14 | color: #fff; 15 | height: 176px; 16 | background: rgb(63,81,181); 17 | display: flex; 18 | align-items: center; 19 | justify-content: space-between; 20 | } 21 | .welcome-card > .mdl-card__title > h2 { 22 | margin: 0; 23 | } 24 | .welcome-card > .mdl-card__title > img { 25 | height: 256px; 26 | margin-left: 16px; 27 | filter: brightness(0) invert(1); 28 | } 29 | .welcome-card > .mdl-card__supporting-text { 30 | font-size: 1.1em; 31 | line-height: 1.4; 32 | padding: 24px; 33 | } 34 | .site-logo { 35 | height: 32px; 36 | margin-left: 20px; 37 | margin-right: 10px; 38 | filter: invert(1); 39 | 40 | } 41 | .drawer-logo { 42 | height: 24px; 43 | margin-right: 8px; 44 | vertical-align: middle; 45 | } 46 | .mdl-layout__drawer .mdl-layout-title { 47 | display: flex; 48 | align-items: center; 49 | padding: 16px; 50 | line-height: normal; 51 | } 52 | .footer-text { 53 | flex-shrink: 0; 54 | text-align: center; 55 | padding: 20px 0; 56 | color: #5f6368; 57 | display: flex; 58 | align-items: center; 59 | justify-content: center; 60 | gap: 12px; 61 | background-color: #f5f5f5; 62 | box-shadow: 0 -2px 4px rgba(0,0,0,0.1); 63 | position: fixed; 64 | bottom: 0; 65 | left: 0; 66 | right: 0; 67 | width: 100%; 68 | z-index: 1000; 69 | } 70 | .footer-text a { 71 | color: #1a73e8; 72 | text-decoration: none; 73 | } 74 | .footer-text a:hover { 75 | text-decoration: underline; 76 | } 77 | .footer-icons { 78 | font-family: 'Material Icons'; 79 | color: #1a73e8; 80 | font-size: 20px; 81 | } 82 | .feed-row { transition: background-color 2s ease; } 83 | .rgb-cell { transition: color 0.5s ease, background-color 0.5s ease; } 84 | input[type="search"]::-webkit-search-cancel-button { -webkit-appearance: searchfield-cancel-button; } 85 | .mdl-card { 86 | width: 100%; 87 | margin-bottom: 24px; 88 | } 89 | .mdl-navigation__link.active { 90 | background: rgba(255,255,255,0.1); 91 | } 92 | .mdl-card__supporting-text { 93 | width: auto; 94 | padding: 24px; 95 | } 96 | .mdl-textfield { 97 | width: 100%; 98 | } 99 | 100 | /* Adjustments for the thingspeak page */ 101 | 102 | .mdl-textfield__input[type="number"] { 103 | appearance: none; 104 | -moz-appearance: textfield; 105 | } 106 | 107 | .mdl-textfield__input[type="number"]::-webkit-outer-spin-button, 108 | .mdl-textfield__input[type="number"]::-webkit-inner-spin-button { 109 | -webkit-appearance: none; 110 | margin: 0; 111 | } 112 | 113 | .new-data { 114 | background-color: #e0f7fa; /* Light cyan background for new data */ 115 | transition: background-color 2s ease; 116 | } 117 | 118 | .feed-row { 119 | transition: background-color 2s ease; 120 | } 121 | 122 | .rgb-cell { 123 | transition: color 0.5s ease, background-color 0.5s ease; 124 | } 125 | 126 | .mdl-data-table__cell--non-numeric { 127 | text-align: left; 128 | } 129 | 130 | .mdl-textfield.select { 131 | position: relative; 132 | } 133 | 134 | .mdl-textfield.select:after { 135 | content: ''; 136 | position: absolute; 137 | top: calc(50% - 8px); 138 | right: 0; 139 | border-top: 8px solid #5f5f5f; 140 | border-left: 8px solid transparent; 141 | border-right: 8px solid transparent; 142 | pointer-events: none; 143 | } 144 | 145 | .mdl-textfield.select select { 146 | -webkit-appearance: none; 147 | -moz-appearance: none; 148 | appearance: none; 149 | width: calc(100% - 32px); 150 | border: none; 151 | background: transparent; 152 | font-size: 16px; 153 | margin: 0; 154 | padding: 4px 0; 155 | } 156 | 157 | .mdl-textfield.is-focused .mdl-textfield__label { 158 | color: #3f51b5; 159 | } 160 | 161 | .mdl-textfield.select .mdl-textfield__label { 162 | position: absolute; 163 | pointer-events: none; 164 | left: 0; 165 | top: 20px; 166 | transition: .2s ease all; 167 | color: rgba(0,0,0, 0.26); 168 | } 169 | 170 | .mdl-textfield.select.is-dirty .mdl-textfield__label, 171 | .mdl-textfield.select.is-focused .mdl-textfield__label { 172 | top: 4px; 173 | font-size: 12px; 174 | color: #3f51b5; 175 | } 176 | 177 | .table-container { 178 | max-height: calc(100vh - 400px); /* Adjust the value based on your header/footer heights */ 179 | overflow-y: auto; 180 | margin-bottom: 20px; /* Space between table and footer */ 181 | } 182 | 183 | .table-container table { 184 | width: 100%; 185 | } 186 | 187 | /* Optional: Keep the header fixed while scrolling */ 188 | .table-container thead th { 189 | position: sticky; 190 | top: 0; 191 | background: white; /* Match your table header background */ 192 | z-index: 1; 193 | } 194 | 195 | /* Navigation link styles */ 196 | .mdl-layout__header .mdl-navigation__link { 197 | color: rgba(255, 255, 255, 0.87); 198 | font-weight: 500; 199 | padding: 0 24px; 200 | height: 36px; 201 | line-height: 36px; 202 | border-radius: 18px; 203 | margin: 0 4px; 204 | transition: background-color 0.2s ease, color 0.2s ease; 205 | } 206 | 207 | .mdl-layout__header .mdl-navigation__link:hover { 208 | background-color: rgba(255, 255, 255, 0.12); 209 | color: #ffffff; 210 | } 211 | 212 | .mdl-layout__header .mdl-navigation__link.active { 213 | background-color: rgba(255, 255, 255, 0.16); 214 | color: #ffffff; 215 | } 216 | 217 | .site-title-link { 218 | display: flex; 219 | align-items: center; 220 | text-decoration: none; 221 | color: inherit; 222 | } 223 | 224 | .site-title-link:hover { 225 | text-decoration: none; 226 | color: inherit; 227 | } 228 | 229 | /* Navigation container styles */ 230 | .nav-container { 231 | display: flex; 232 | align-items: center; 233 | } 234 | 235 | /* Responsive adjustments */ 236 | @media screen and (max-width: 480px) { 237 | .mdl-layout__header-row { 238 | padding-left: 16px; 239 | padding-right: 16px; 240 | } 241 | 242 | .site-logo { 243 | margin-left: 0; 244 | margin-right: 8px; 245 | } 246 | 247 | .mdl-layout-title { 248 | font-size: 18px; 249 | } 250 | 251 | .mdl-layout__header .mdl-navigation__link { 252 | padding: 0 12px; 253 | margin: 0 2px; 254 | } 255 | } 256 | -------------------------------------------------------------------------------- /app/thingspeak.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | IoT Debugger - ThingSpeak 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 360 | 361 | 362 |
363 | 376 | 377 |
378 |
379 |
380 | 381 |
382 |

ThingSpeak Channel Data

383 |
384 | 385 |
386 |
387 | 388 | 389 |
390 |
391 | 392 |
393 |
394 | 395 | 396 |
397 |
398 | 399 |
400 |
401 | 402 | 403 |
404 |
405 | 406 |
407 |
408 | 409 | 410 |
411 |
412 | 413 |
414 | 417 | 420 |
421 |
422 | 425 |
426 |
427 |
428 | 429 | 430 |
431 | 432 |

433 |

Channel Data

434 |
435 | 436 | 437 |
438 |
439 |
440 |
441 |
442 |
443 | 444 | 452 |
453 | 454 | 455 | --------------------------------------------------------------------------------