├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── boards └── neurite.json ├── cmds.md ├── fs ├── makefs.sh └── src │ ├── README.md │ ├── config.json │ ├── favicon.ico │ └── index.html ├── hardware ├── PCB-ScreenShot.png ├── neurite-brd-white.png ├── neurite-breadboard.png ├── neurite-core.brd ├── neurite-core.pdf ├── neurite-core.sch └── neurite-pcb-n-bread.png ├── lib └── readme.txt ├── patch ├── 0001-enable-debug-for-OTA.patch ├── 0001-fix-newlines.patch └── 0001-increase-mqtt-msg-size-to-256.patch ├── platformio.ini ├── prebuild ├── firmware.bin.gz ├── firmware.dev.bin.gz ├── spiffs.1m.bin.gz └── spiffs.64k.bin.gz └── src ├── neurite.ino ├── neurite_priv.h ├── neurite_user.ino └── neurite_utils.h /.gitignore: -------------------------------------------------------------------------------- 1 | *cscope* 2 | .pioenvs 3 | .piolibdeps/ 4 | fs/tmp 5 | fs/spiffs.1m.bin 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # 2 | # PlatformIO Libraries: 3 | # 4 | # [ ID ] Name URL 5 | # --------------------------------------------------------------------- 6 | # [ 64 ] Json http://platformio.org/#!/lib/show/64/Json 7 | # [ 89 ] PubSubClient http://platformio.org/#!/lib/show/89/PubSubClient 8 | # 9 | 10 | language: python 11 | python: 12 | - '2.7' 13 | sudo: false 14 | cache: 15 | directories: 16 | - ~/.platformio 17 | env: 18 | - PLATFORMIO_CI_SRC=src 19 | install: 20 | - echo '[install]' 21 | - pip install -U platformio 22 | - platformio lib install PubSubClient ArduinoJson 23 | before_script: 24 | - echo '[before_script]' 25 | script: 26 | - echo '[script]' 27 | - platformio run 28 | notifications: 29 | slack: 30 | rooms: 31 | - linkgo-io:csFT4H0MBCbg35MQUpEEjRfd#github-linkgo 32 | deploy: 33 | provider: releases 34 | api_key: 35 | secure: ofjZq7bRWUW4sYprfKrxtnQ77KXjMKNgdFHj6ZArDbX0Uc96D//iSRFaZ+KzMGD9eD1Rm0ETimYriXgPGsfS461kcyB/Rw8kyCDgR+jsrNCfFUu6giaCdLUNp0+EZlk7Ohvy4EeHknpVRmqedrPStx+H0NA+7nO1xNgF0kGNtELgve+D8OhDPMtG8YgxkI9vFGbyZz4pIDMIn/OTtB5y4iDqlLwzxnHb4olobfgFdYI2yJQZ+JAfEL7bxmVXvKk3B75PbkbTv65o1gtYBg4dJ8IUoBHlCvYbWalj3uNdAzy2cXuaD8JrPFnOZ/hJhaT231MXS9s5GPiyEOoFugY9JeUgzS97pMQNoquLslodwOFjfZ6eVeIRQ5Nq43bOa67tatSJi7cc5EXEdeId9J0PA423NkhDmjGwrjT6aiyVw4wP00u5hKgkwcGjkfbS0pQvWxqFKVfr5Lnw67b7FoWjB14PCSLGtdELD+SSpykF2vYKJ8rxvycsSblf+kBrifrrEZJThVAqsJn3d7riMZ1UEMeGwoTC6C5xyFX3v7SeG2R78vyREA4ZNqTE8rjeo7mFXtG+ZiUpXyS+KmhoCfiiEZcI0zIN0wl27wDWbCuAsOnrdImSyiRFAPxiiYFz0yJQY3pJgMZQ6tkE5WLh6sayet6Knzf+1WBwJm/V4CbxkKI= 36 | file: 37 | - .pioenvs/neurite/firmware.bin 38 | skip_cleanup: true 39 | on: 40 | tags: true 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015-2016 Linkgo LLC 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 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [English](#) | [中文](#) 2 | 3 | # Neurite [![Linux build status](https://travis-ci.org/linkgo/neurite.svg)](https://travis-ci.org/linkgo/neurite) 4 | 5 | A serial to MQTT bridge, an easier way to build IoT product with esp8266 Arduino. 6 | 7 | ![pcb-n-bread](https://raw.githubusercontent.com/linkgo/neurite/master/hardware/neurite-pcb-n-bread.png) 8 | 9 | ## Contents 10 | - [Introduction](#introduction) 11 | - [What Is It](#what-is-it) 12 | - [Who Need It](#who-need-it) 13 | - [Features](#features) 14 | - [How It Works](#how-it-works) 15 | - [User Tutorial](#user-tutorial) 16 | - [Developer Tutorial](#developer-tutorial) 17 | - [Credits](#credits) 18 | - [License](#license) 19 | 20 | 21 | ## Introduction 22 | 23 | Neurite is named from the neural network, who takes charge of signal and information transmitting. 24 | In the world of IoT, the amount of smart units may be explosively large. 25 | Thus we are introducing Neurite, to simplify your next smart design. 26 | 27 | 28 | ### What Is It 29 | 30 | 31 | * Neurite is an esp8266 Arduino. 32 | * Neurite is a serial to MQTT bridge. 33 | * Neurite is a WiFi module running corresponding firmware. 34 | * Neurite is simply designed to be Plug-n-Play. 35 | 36 | 37 | ### Who Need It 38 | 39 | **Neurite is great for you if:** 40 | 41 | * You just wish to connect existing hardware to the internet and publish/subscribe data. 42 | * You just want an easy way for all your devices to communicate with each other. 43 | 44 | **Neurite can do a lot help if:** 45 | 46 | * You'd like to build some MQTT ready product quickly. 47 | * You need a hardware to integrate into your web service without pain. 48 | * You are looking for an easier IoT solution. 49 | * You are neat hackers. ;) 50 | 51 | 52 | ### Features 53 | 54 | **Basic:** 55 | 56 | * Neurite natively supports MQTT. 57 | * Neurite publishes data from serial port to the internet. 58 | * Neurite subscribes internet data and transfers to serial port. 59 | * Neurite can be dynamically configured over the internet. 60 | * Neurite is OTA enabled, for both firmware and filesystem. 61 | * Neurite will automatically reconnect once there's network issue. 62 | 63 | **Advanced:** 64 | 65 | * Neurite supports all kinds of sensors and peripherals interfaced with SPI/I2C or GPIO 66 | * Neurite benefits from 3rd party libraries thanks to esp8266 Arduino. 67 | * Neurite is fully customizable and hackable. 68 | 69 | 70 | ### How It Works 71 | 72 | Neurite is powered by [esp8266 Arduino](https://github.com/esp8266/Arduino), developed with [PlatformIO](http://platformio.org/). 73 | 74 | Typical work flow: 75 | 76 | 1. Get Neurite connected to local WiFi Access Point. 77 | 2. Neurite connects to [linkgo MQTT broker](#), and subscribes to a configurable topic. 78 | 3. Neurite listens to serial port and MQTT, transparently bridges them two. 79 | 80 | Advanced work flow besides above: 81 | 82 | 4. Neurite loops user task within a configurable interval. 83 | 5. MQTT message callbacks are registered to user logic. 84 | 85 | 86 | ## User Tutorial 87 | 88 | 1. First time setup. 89 | > Power on your Neurite. Switch to AP mode for the first time config, by pressing the button (over 5 seconds) until LED stops flashing. 90 | 91 | 2. Configure Neurite to connect to your local WiFi Access Point. 92 | > Connect your phone, pad or laptop to `neurite-*`, navigate your browser to `linkgo.io`, choose the WiFi AP should Neurite connect to. Then Neurite will automatically reboot. 93 | 94 | 3. Wait until Neurite gets online. 95 | > Neurite LED flashes fast indicates trying hard to connect according to the WiFi ssid and psk you just provided. It turns to be breathing once connected. 96 | 97 | 4. All set. 98 | > Now you can send/receive messages through Neurite serial port. 99 | > And Neurite will automatically connect to the WiFi AP next time. 100 | 101 | 102 | ## Developer Tutorial 103 | 104 | TODO 105 | 106 | 107 | ## Credits 108 | 109 | [igrr](https://github.com/igrr) and all the brilliant contributors for [esp8266 Arduino](https://github.com/esp8266/Arduino). 110 | 111 | 112 | ## License 113 | 114 | > The MIT License (MIT) 115 | > 116 | > Copyright (c) 2015-2016 Linkgo LLC 117 | > 118 | > Permission is hereby granted, free of charge, to any person obtaining a copy 119 | > of this software and associated documentation files (the "Software"), to deal 120 | > in the Software without restriction, including without limitation the rights 121 | > to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 122 | > copies of the Software, and to permit persons to whom the Software is 123 | > furnished to do so, subject to the following conditions: 124 | > 125 | > The above copyright notice and this permission notice shall be included in all 126 | > copies or substantial portions of the Software. 127 | > 128 | > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 129 | > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 130 | > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 131 | > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 132 | > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 133 | > OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 134 | > SOFTWARE. 135 | -------------------------------------------------------------------------------- /boards/neurite.json: -------------------------------------------------------------------------------- 1 | { 2 | "build": { 3 | "core": "esp8266", 4 | "extra_flags": "-DESP8266 -DARDUINO_ARCH_ESP8266 -DARDUINO_ESP8266_ESP12", 5 | "f_cpu": "80000000L", 6 | "f_flash": "40000000L", 7 | "flash_mode": "dio", 8 | "ldscript": "eagle.flash.4m1m.ld", 9 | "mcu": "esp8266", 10 | "variant": "nodemcu" 11 | }, 12 | "frameworks": ["arduino"], 13 | "name": "Neurite by Linkgo LLC", 14 | "platform": "espressif8266", 15 | "upload": { 16 | "maximum_ram_size": 81920, 17 | "maximum_size": 4194304, 18 | "resetmethod": "ck", 19 | "require_upload_port" : true, 20 | "speed": 115200 21 | }, 22 | "url": "http://linkgo.io", 23 | "vendor": "Linkgo LLC" 24 | } 25 | -------------------------------------------------------------------------------- /cmds.md: -------------------------------------------------------------------------------- 1 | Sample Commands 2 | =============== 3 | 4 | ap mode fs operation 5 | -------------------- 6 | curl -X DELETE 'http://192.168.1.23/edit?dir=/index.html.gz' 7 | curl -X GET 'http://192.168.1.23/list?dir=/' 8 | curl -F "file=@index.html.gz" http://192.168.1.23/edit 9 | for file in `ls -A1`; do curl -F "file=@$PWD/$file" http://192.168.1.23/edit; done 10 | 11 | 512k (64k spiffs) 12 | ----------------- 13 | mkspiffs -c ./data -p 256 -b 4096 -s 65536 spiffs.64k.bin 14 | esptool -cd ck -cb 115200 -cp /dev/ttyUSB1 -ca 0x6b000 -cf spiffs.64k.bin 15 | 16 | 4m (1m spiffs) 17 | -------------- 18 | mkspiffs -c ./data -p 256 -b 8192 -s 1028096 spiffs.1m.bin 19 | esptool -cd ck -cb 115200 -cp /dev/ttyUSB1 -ca 0x300000 -cf spiffs.1m.bin 20 | 21 | flash firmware 22 | -------------- 23 | esptool -vv -cd ck -cb 115200 -cp /dev/ttyUSB1 -ca 0x00000 -cf neurite.cpp.bin 24 | 25 | mqtt push ota 26 | ------------- 27 | mqtt publish -h accrete.org -t /neuro/neurite-00016694/ota 'http://192.168.100.154:8080/firmware/esp.bin' 28 | 29 | mqtt config 30 | ----------- 31 | mqtt publish -h accrete.org -t /neuro/neurite-000c1632/config/ssid -m 'linkgo.io' 32 | mqtt publish -h accrete.org -t /neuro/neurite-000c1632/config/psk -m 'ilovelinkgo' 33 | mqtt publish -h accrete.org -t /neuro/neurite-000c1632/config/topic_from -m '/neuro/chatroom' 34 | mqtt publish -h accrete.org -t /neuro/neurite-000c1632/config/topic_to -m '/neuro/chatroom' 35 | mqtt publish -h accrete.org -t /neuro/neurite-000c1632/reboot -m "1" 36 | 37 | -------------------------------------------------------------------------------- /fs/makefs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo "make spiffs start ..." 4 | 5 | rm -rf tmp 6 | mkdir tmp 7 | cp src/* tmp/ 8 | which html-minifier 9 | if [ $? -eq 0 ]; then 10 | echo "try to minify html"; 11 | html-minifier --minify-css --minify-js --collapse-boolean-attributes --collapse-whitespace --decode-entities --html-5 --process-conditional-comments --remove-attribute-quotes --remove-comments --remove-empty-attributes --remove-optional-tags --remove-redundant-attributes --remove-script-type-attributes --remove-style-link-type-attributes --remove-tag-whitespace --sort-attributes --sort-class-name --use-short-doctype -o tmp/index.html src/index.html 12 | else 13 | echo "gzip without minified"; 14 | fi 15 | gzip tmp/index.html 16 | mkspiffs -c ./tmp -p 256 -b 8192 -s 1028096 spiffs.1m.bin 17 | 18 | echo "make spiffs done" 19 | -------------------------------------------------------------------------------- /fs/src/README.md: -------------------------------------------------------------------------------- 1 | file system 2 | =========== 3 | 4 | We use spiffs for file system storage. 5 | The directory contains the raw files. 6 | -------------------------------------------------------------------------------- /fs/src/config.json: -------------------------------------------------------------------------------- 1 | {"ssid":"linkgo.io","psk":"ilovelinkgo","topic_to":"/neuro/chatroom","topic_from":"/neuro/chatroom"} 2 | -------------------------------------------------------------------------------- /fs/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkgo/neurite/ed3504ef2a637ba1986b1d1fbdedaa6434e4d1a9/fs/src/favicon.ico -------------------------------------------------------------------------------- /hardware/PCB-ScreenShot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkgo/neurite/ed3504ef2a637ba1986b1d1fbdedaa6434e4d1a9/hardware/PCB-ScreenShot.png -------------------------------------------------------------------------------- /hardware/neurite-brd-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkgo/neurite/ed3504ef2a637ba1986b1d1fbdedaa6434e4d1a9/hardware/neurite-brd-white.png -------------------------------------------------------------------------------- /hardware/neurite-breadboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkgo/neurite/ed3504ef2a637ba1986b1d1fbdedaa6434e4d1a9/hardware/neurite-breadboard.png -------------------------------------------------------------------------------- /hardware/neurite-core.brd: -------------------------------------------------------------------------------- 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 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | * 176 | Neurite 177 | linkgo.io 178 | 1.GND 179 | 2.RXD 180 | 3.TXD 181 | 4.VCC 182 | 5.ADC 183 | 6.GPIO12 184 | 7.GPIO13 185 | 8.GPIO14 186 | 187 | BUTTON.GPIO0 188 | LED.GPIO5 189 | LED.POWER 190 | (3.3V-5V) 191 | 192 | 193 | 194 | <h3>SparkFun Electronics' preferred foot prints</h3> 195 | In this library you'll find resistors, capacitors, inductors, test points, jumper pads, etc.<br><br> 196 | We've spent an enormous amount of time creating and checking these footprints and parts, but it is the end user's responsibility to ensure correctness and suitablity for a given componet or application. If you enjoy using this library, please buy one of our products at www.sparkfun.com. 197 | <br><br> 198 | <b>Licensing:</b> Creative Commons ShareAlike 4.0 International - https://creativecommons.org/licenses/by-sa/4.0/ 199 | <br><br> 200 | You are welcome to use this library for commercial purposes. For attribution, we ask that when you begin to sell your device using our footprint, you email us with a link to the product being sold. We want bragging rights that we helped (in a very small part) to create your 8th world wonder. We would like the opportunity to feature your device on our homepage. 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | >NAME 213 | >VALUE 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | >NAME 224 | >VALUE 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | >Name 276 | >Value 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | >Name 337 | >Value 338 | 339 | 340 | 341 | 342 | <h3>SparkFun Electronics' preferred foot prints</h3> 343 | In this library you'll find discrete semiconductors- transistors, diodes, TRIACs, optoisolators, etc.<br><br> 344 | We've spent an enormous amount of time creating and checking these footprints and parts, but it is the end user's responsibility to ensure correctness and suitablity for a given componet or application. If you enjoy using this library, please buy one of our products at www.sparkfun.com. 345 | <br><br> 346 | <b>Licensing:</b> Creative Commons ShareAlike 4.0 International - https://creativecommons.org/licenses/by-sa/4.0/ 347 | <br><br> 348 | You are welcome to use this library for commercial purposes. For attribution, we ask that when you begin to sell your device using our footprint, you email us with a link to the product being sold. We want bragging rights that we helped (in a very small part) to create your 8th world wonder. We would like the opportunity to feature your device on our homepage. 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | >NAME 363 | >VALUE 364 | 365 | 366 | 367 | 368 | <h3>SparkFun Electronics' preferred foot prints</h3> 369 | In this library you'll find drivers, regulators, and amplifiers.<br><br> 370 | We've spent an enormous amount of time creating and checking these footprints and parts, but it is the end user's responsibility to ensure correctness and suitablity for a given componet or application. If you enjoy using this library, please buy one of our products at www.sparkfun.com. 371 | <br><br> 372 | <b>Licensing:</b> Creative Commons ShareAlike 4.0 International - https://creativecommons.org/licenses/by-sa/4.0/ 373 | <br><br> 374 | You are welcome to use this library for commercial purposes. For attribution, we ask that when you begin to sell your device using our footprint, you email us with a link to the product being sold. We want bragging rights that we helped (in a very small part) to create your 8th world wonder. We would like the opportunity to feature your device on our homepage. 375 | 376 | 377 | <b>Small Outline Transistor</b> 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | >NAME 391 | >VALUE 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | <h3>SparkFun Electronics' preferred foot prints</h3> 402 | In this library you'll find discrete LEDs for illumination or indication, but no displays.<br><br> 403 | We've spent an enormous amount of time creating and checking these footprints and parts, but it is the end user's responsibility to ensure correctness and suitablity for a given componet or application. If you enjoy using this library, please buy one of our products at www.sparkfun.com. 404 | <br><br> 405 | <b>Licensing:</b> Creative Commons ShareAlike 4.0 International - https://creativecommons.org/licenses/by-sa/4.0/ 406 | <br><br> 407 | You are welcome to use this library for commercial purposes. For attribution, we ask that when you begin to sell your device using our footprint, you email us with a link to the product being sold. We want bragging rights that we helped (in a very small part) to create your 8th world wonder. We would like the opportunity to feature your device on our homepage. 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | >NAME 417 | >VALUE 418 | 419 | 420 | 421 | 422 | Spark Fun Electronics' preferred foot prints. <b>Not to be used for commercial purposes.</b> We've spent an enormous amount of time creating and checking these footprints and parts. If you enjoy using this library, please buy one of our products at www.sparkfun.com. 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | >NAME 456 | >VALUE 457 | 458 | 459 | 460 | 461 | 462 | 463 | Footprint for Part#1575AT43A40 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | >NAME 477 | >VALUE 478 | 479 | 480 | 481 | Fits EIAJ packages (wide version of the SOIC-8). 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | >VALUE 496 | >NAME 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | >NAME 515 | >VALUE 516 | 517 | 518 | <b>CAPACITOR</b><p> 519 | chip 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | >NAME 529 | >VALUE 530 | 531 | 532 | 533 | 534 | 535 | 536 | <b>CAPACITOR</b><p> 537 | chip 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | >NAME 548 | >VALUE 549 | 550 | 551 | 552 | 553 | 554 | <b>CAPACITOR</b><p> 555 | chip 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | >NAME 565 | >VALUE 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | <b>EAGLE Design Rules</b> 596 | <p> 597 | Die Standard-Design-Rules sind so gewählt, dass sie für 598 | die meisten Anwendungen passen. Sollte ihre Platine 599 | besondere Anforderungen haben, treffen Sie die erforderlichen 600 | Einstellungen hier und speichern die Design Rules unter 601 | einem neuen Namen ab. 602 | <b>EAGLE Design Rules</b> 603 | <p> 604 | The default Design Rules have been set to cover 605 | a wide range of applications. Your particular design 606 | may have different requirements, so please make the 607 | necessary adjustments and save your customized 608 | design rules under a new name. 609 | <b>EAGLE Design Rules</b> 610 | <p>这是一个按照深圳嘉利创公司所公布的生产工艺规范所制定的设计规则<br/><br/> 611 | 层数 1~6层<br/> 612 | 板材类型 FR-4板材<br/> 613 | 最小线宽 6mil<br/> 614 | 最小间隙 6mil<br/> 615 | 成品外层铜厚 1oz~2oz(35um~70um)<br/> 616 | 成品内层铜厚 0.5oz(17um)<br/> 617 | 钻孔孔径(机械钻) 0.3~6.3mm <br/> 618 | 过孔单边焊环 ≥6mil<br/> 619 | 最小字符宽 6mil<br/> 620 | 最小字符高 ≥1mm<br/> 621 | 走线与外形间距 ≥0.3mm<br/> 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 682 | 683 | 684 | 685 | 686 | 687 | 688 | 689 | 690 | 691 | 692 | 693 | 694 | 695 | 696 | 697 | 698 | 699 | 700 | 701 | 702 | 703 | 704 | 705 | 706 | 707 | 708 | 709 | 710 | 711 | 712 | 713 | 714 | 715 | 716 | 717 | 718 | 719 | 720 | 721 | 722 | 723 | 724 | 725 | 726 | 727 | 728 | 729 | 730 | 731 | 732 | 733 | 734 | 735 | 736 | 737 | 738 | 739 | 740 | 741 | 742 | 743 | 744 | 745 | 746 | 747 | 748 | 749 | 750 | 751 | 752 | 753 | 754 | 755 | 756 | 757 | 758 | 759 | 760 | 761 | 762 | 763 | 764 | 765 | 766 | 767 | 768 | 769 | 770 | 771 | 772 | 773 | 774 | 775 | 776 | 777 | 778 | 779 | 780 | 781 | 782 | 783 | 784 | 785 | 786 | 787 | 788 | 789 | 790 | 791 | 792 | 793 | 794 | 795 | 796 | 797 | 798 | 799 | 800 | 801 | 802 | 803 | 804 | 805 | 806 | 807 | 808 | 809 | 810 | 811 | 812 | 813 | 814 | 815 | 816 | 817 | 818 | 819 | 820 | 821 | 822 | 823 | 824 | 825 | 826 | 827 | 828 | 829 | 830 | 831 | 832 | 833 | 834 | 835 | 836 | 837 | 838 | 839 | 840 | 841 | 842 | 843 | 844 | 845 | 846 | 847 | 848 | 849 | 850 | 851 | 852 | 853 | 854 | 855 | 856 | 857 | 858 | 859 | 860 | 861 | 862 | 863 | 864 | 865 | 866 | 867 | 868 | 869 | 870 | 871 | 872 | 873 | 874 | 875 | 876 | 877 | 878 | 879 | 880 | 881 | 882 | 883 | 884 | 885 | 886 | 887 | 888 | 889 | 890 | 891 | 892 | 893 | 894 | 895 | 896 | 897 | 898 | 899 | 900 | 901 | 902 | 903 | 904 | 905 | 906 | 907 | 908 | 909 | 910 | 911 | 912 | 913 | 914 | 915 | 916 | 917 | 918 | 919 | 920 | 921 | 922 | 923 | 924 | 925 | 926 | 927 | 928 | 929 | 930 | 931 | 932 | 933 | 934 | 935 | 936 | 937 | 938 | 939 | 940 | 941 | 942 | 943 | 944 | 945 | 946 | 947 | 948 | 949 | 950 | 951 | 952 | 953 | 954 | 955 | 956 | 957 | 958 | 959 | 960 | 961 | 962 | 963 | 964 | 965 | 966 | 967 | 968 | 969 | 970 | 971 | 972 | 973 | 974 | 975 | 976 | 977 | 978 | 979 | 980 | 981 | 982 | 983 | 984 | 985 | 986 | 987 | 988 | 989 | 990 | 991 | 992 | 993 | 994 | 995 | 996 | 997 | 998 | 999 | 1000 | 1001 | 1002 | 1003 | 1004 | 1005 | 1006 | 1007 | 1008 | 1009 | 1010 | 1011 | 1012 | 1013 | 1014 | 1015 | 1016 | 1017 | 1018 | 1019 | 1020 | 1021 | 1022 | 1023 | 1024 | 1025 | 1026 | 1027 | 1028 | 1029 | 1030 | 1031 | 1032 | 1033 | 1034 | 1035 | 1036 | 1037 | 1038 | 1039 | 1040 | 1041 | 1042 | 1043 | 1044 | 1045 | 1046 | 1047 | 1048 | 1049 | 1050 | 1051 | 1052 | 1053 | 1054 | 1055 | 1056 | 1057 | 1058 | 1059 | 1060 | 1061 | 1062 | 1063 | 1064 | 1065 | 1066 | 1067 | 1068 | 1069 | 1070 | 1071 | 1072 | 1073 | 1074 | 1075 | 1076 | 1077 | 1078 | 1079 | 1080 | 1081 | 1082 | 1083 | 1084 | 1085 | 1086 | 1087 | 1088 | 1089 | 1090 | 1091 | 1092 | 1093 | 1094 | 1095 | 1096 | 1097 | 1098 | 1099 | 1100 | 1101 | 1102 | 1103 | 1104 | 1105 | 1106 | 1107 | 1108 | 1109 | 1110 | 1111 | 1112 | 1113 | 1114 | 1115 | 1116 | 1117 | 1118 | 1119 | 1120 | 1121 | 1122 | 1123 | 1124 | 1125 | 1126 | 1127 | 1128 | 1129 | 1130 | 1131 | 1132 | 1133 | 1134 | 1135 | 1136 | 1137 | 1138 | 1139 | 1140 | 1141 | 1142 | 1143 | 1144 | 1145 | 1146 | 1147 | 1148 | 1149 | 1150 | 1151 | 1152 | 1153 | 1154 | 1155 | 1156 | 1157 | 1158 | 1159 | 1160 | 1161 | 1162 | 1163 | 1164 | 1165 | 1166 | 1167 | 1168 | 1169 | 1170 | 1171 | 1172 | 1173 | 1174 | 1175 | 1176 | 1177 | 1178 | 1179 | 1180 | 1181 | 1182 | 1183 | 1184 | 1185 | 1186 | 1187 | 1188 | 1189 | 1190 | 1191 | 1192 | 1193 | 1194 | 1195 | 1196 | 1197 | 1198 | 1199 | 1200 | 1201 | 1202 | 1203 | 1204 | 1205 | 1206 | 1207 | 1208 | 1209 | 1210 | 1211 | 1212 | 1213 | 1214 | 1215 | 1216 | 1217 | 1218 | 1219 | 1220 | 1221 | 1222 | 1223 | 1224 | 1225 | 1226 | 1227 | 1228 | 1229 | 1230 | 1231 | 1232 | 1233 | 1234 | 1235 | 1236 | 1237 | 1238 | 1239 | 1240 | 1241 | 1242 | 1243 | 1244 | 1245 | 1246 | 1247 | 1248 | 1249 | 1250 | 1251 | 1252 | 1253 | 1254 | 1255 | 1256 | 1257 | 1258 | 1259 | 1260 | 1261 | 1262 | 1263 | 1264 | 1265 | 1266 | 1267 | 1268 | 1269 | 1270 | 1271 | 1272 | 1273 | 1274 | 1275 | 1276 | 1277 | 1278 | 1279 | 1280 | 1281 | 1282 | 1283 | 1284 | 1285 | 1286 | 1287 | 1288 | 1289 | 1290 | 1291 | 1292 | 1293 | 1294 | 1295 | 1296 | 1297 | 1298 | 1299 | 1300 | 1301 | 1302 | 1303 | 1304 | 1305 | 1306 | 1307 | 1308 | 1309 | 1310 | 1311 | 1312 | 1313 | 1314 | 1315 | 1316 | 1317 | 1318 | 1319 | 1320 | 1321 | 1322 | 1323 | 1324 | 1325 | 1326 | 1327 | 1328 | 1329 | 1330 | 1331 | 1332 | 1333 | 1334 | 1335 | 1336 | 1337 | 1338 | 1339 | 1340 | 1341 | 1342 | 1343 | 1344 | 1345 | 1346 | 1347 | 1348 | 1349 | 1350 | 1351 | 1352 | 1353 | 1354 | 1355 | 1356 | 1357 | 1358 | 1359 | 1360 | 1361 | 1362 | 1363 | 1364 | 1365 | 1366 | 1367 | 1368 | 1369 | 1370 | 1371 | 1372 | 1373 | 1374 | 1375 | 1376 | 1377 | 1378 | 1379 | 1380 | 1381 | 1382 | 1383 | 1384 | 1385 | 1386 | 1387 | 1388 | 1389 | 1390 | 1391 | 1392 | 1393 | 1394 | 1395 | 1396 | 1397 | 1398 | 1399 | 1400 | 1401 | 1402 | 1403 | 1404 | 1405 | 1406 | 1407 | 1408 | 1409 | 1410 | 1411 | 1412 | 1413 | 1414 | 1415 | 1416 | 1417 | 1418 | 1419 | 1420 | 1421 | 1422 | 1423 | 1424 | 1425 | 1426 | 1427 | 1428 | 1429 | 1430 | 1431 | 1432 | 1433 | 1434 | 1435 | 1436 | 1437 | 1438 | 1439 | 1440 | 1441 | 1442 | 1443 | 1444 | 1445 | 1446 | 1447 | 1448 | 1449 | 1450 | 1451 | 1452 | 1453 | 1454 | 1455 | 1456 | 1457 | 1458 | 1459 | 1460 | 1461 | 1462 | 1463 | 1464 | 1465 | 1466 | 1467 | 1468 | 1469 | 1470 | 1471 | 1472 | 1473 | 1474 | 1475 | 1476 | 1477 | 1478 | 1479 | 1480 | 1481 | 1482 | 1483 | 1484 | 1485 | 1486 | 1487 | 1488 | 1489 | 1490 | 1491 | 1492 | 1493 | 1494 | 1495 | 1496 | 1497 | 1498 | 1499 | 1500 | 1501 | 1502 | 1503 | 1504 | 1505 | 1506 | 1507 | 1508 | 1509 | 1510 | 1511 | 1512 | 1513 | 1514 | 1515 | 1516 | 1517 | 1518 | 1519 | 1520 | 1521 | 1522 | 1523 | 1524 | 1525 | 1526 | 1527 | 1528 | 1529 | 1530 | 1531 | 1532 | 1533 | 1534 | 1535 | 1536 | 1537 | 1538 | 1539 | 1540 | 1541 | 1542 | 1543 | 1544 | 1545 | 1546 | 1547 | 1548 | 1549 | 1550 | 1551 | 1552 | 1553 | 1554 | 1555 | 1556 | 1557 | 1558 | 1559 | 1560 | 1561 | 1562 | 1563 | 1564 | 1565 | 1566 | 1567 | 1568 | 1569 | 1570 | 1571 | 1572 | 1573 | 1574 | 1575 | 1576 | 1577 | 1578 | 1579 | 1580 | 1581 | 1582 | 1583 | 1584 | 1585 | 1586 | 1587 | 1588 | 1589 | 1590 | 1591 | 1592 | 1593 | 1594 | 1595 | 1596 | 1597 | 1598 | 1599 | 1600 | 1601 | 1602 | 1603 | 1604 | 1605 | 1606 | 1607 | 1608 | 1609 | 1610 | 1611 | 1612 | 1613 | 1614 | 1615 | 1616 | 1617 | 1618 | 1619 | 1620 | 1621 | 1622 | 1623 | 1624 | 1625 | 1626 | 1627 | 1628 | 1629 | 1630 | 1631 | 1632 | 1633 | 1634 | 1635 | 1636 | 1637 | 1638 | 1639 | 1640 | 1641 | 1642 | 1643 | 1644 | 1645 | 1646 | 1647 | 1648 | 1649 | 1650 | 1651 | 1652 | 1653 | 1654 | 1655 | 1656 | 1657 | 1658 | 1659 | 1660 | 1661 | 1662 | 1663 | 1664 | 1665 | 1666 | 1667 | 1668 | 1669 | 1670 | 1671 | 1672 | 1673 | 1674 | 1675 | 1676 | 1677 | 1678 | 1679 | 1680 | 1681 | 1682 | 1683 | 1684 | 1685 | 1686 | 1687 | 1688 | 1689 | 1690 | 1691 | 1692 | 1693 | 1694 | 1695 | 1696 | 1697 | 1698 | 1699 | 1700 | 1701 | 1702 | 1703 | 1704 | 1705 | 1706 | 1707 | 1708 | 1709 | 1710 | 1711 | 1712 | 1713 | 1714 | 1715 | 1716 | 1717 | 1718 | 1719 | 1720 | 1721 | 1722 | 1723 | 1724 | 1725 | 1726 | 1727 | 1728 | 1729 | 1730 | 1731 | 1732 | 1733 | 1734 | 1735 | 1736 | 1737 | 1738 | 1739 | 1740 | 1741 | 1742 | 1743 | 1744 | 1745 | 1746 | 1747 | 1748 | 1749 | 1750 | 1751 | 1752 | 1753 | 1754 | 1755 | 1756 | 1757 | 1758 | 1759 | 1760 | 1761 | 1762 | 1763 | 1764 | 1765 | 1766 | 1767 | 1768 | 1769 | 1770 | 1771 | 1772 | 1773 | 1774 | 1775 | 1776 | 1777 | 1778 | 1779 | 1780 | 1781 | 1782 | 1783 | 1784 | 1785 | 1786 | 1787 | 1788 | 1789 | 1790 | 1791 | 1792 | 1793 | 1794 | 1795 | 1796 | 1797 | 1798 | 1799 | 1800 | 1801 | 1802 | 1803 | 1804 | 1805 | 1806 | 1807 | 1808 | 1809 | 1810 | 1811 | 1812 | 1813 | 1814 | 1815 | 1816 | 1817 | 1818 | 1819 | 1820 | 1821 | 1822 | 1823 | 1824 | 1825 | 1826 | 1827 | 1828 | 1829 | 1830 | 1831 | 1832 | 1833 | 1834 | 1835 | 1836 | 1837 | 1838 | 1839 | 1840 | 1841 | 1842 | 1843 | 1844 | 1845 | 1846 | 1847 | 1848 | 1849 | 1850 | 1851 | 1852 | 1853 | 1854 | 1855 | 1856 | 1857 | 1858 | 1859 | 1860 | 1861 | 1862 | 1863 | 1864 | 1865 | 1866 | 1867 | 1868 | 1869 | 1870 | 1871 | 1872 | 1873 | 1874 | 1875 | 1876 | 1877 | 1878 | 1879 | 1880 | 1881 | 1882 | 1883 | 1884 | 1885 | 1886 | 1887 | 1888 | 1889 | 1890 | 1891 | 1892 | 1893 | 1894 | 1895 | 1896 | 1897 | 1898 | 1899 | 1900 | 1901 | 1902 | 1903 | 1904 | 1905 | 1906 | 1907 | 1908 | 1909 | 1910 | 1911 | 1912 | 1913 | 1914 | 1915 | 1916 | 1917 | 1918 | 1919 | 1920 | 1921 | 1922 | 1923 | 1924 | 1925 | 1926 | 1927 | -------------------------------------------------------------------------------- /hardware/neurite-core.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkgo/neurite/ed3504ef2a637ba1986b1d1fbdedaa6434e4d1a9/hardware/neurite-core.pdf -------------------------------------------------------------------------------- /hardware/neurite-pcb-n-bread.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkgo/neurite/ed3504ef2a637ba1986b1d1fbdedaa6434e4d1a9/hardware/neurite-pcb-n-bread.png -------------------------------------------------------------------------------- /lib/readme.txt: -------------------------------------------------------------------------------- 1 | This directory is intended for the project specific (private) libraries. 2 | PlatformIO will compile them to static libraries and link to executable file. 3 | 4 | The source code of each library should be placed in separate directory, like 5 | "lib/private_lib/[here are source files]". 6 | 7 | For example, see how can be organised `Foo` and `Bar` libraries: 8 | 9 | |--lib 10 | | |--Bar 11 | | | |--docs 12 | | | |--examples 13 | | | |--src 14 | | | |- Bar.c 15 | | | |- Bar.h 16 | | |--Foo 17 | | | |- Foo.c 18 | | | |- Foo.h 19 | | |- readme.txt --> THIS FILE 20 | |- platformio.ini 21 | |--src 22 | |- main.c 23 | 24 | Then in `src/main.c` you should use: 25 | 26 | #include 27 | #include 28 | 29 | // rest H/C/CPP code 30 | 31 | PlatformIO will find your libraries automatically, configure preprocessor's 32 | include paths and build them. 33 | 34 | See additional options for PlatformIO Library Dependency Finder `lib_*`: 35 | 36 | http://docs.platformio.org/en/latest/projectconf.html#lib-install 37 | -------------------------------------------------------------------------------- /patch/0001-enable-debug-for-OTA.patch: -------------------------------------------------------------------------------- 1 | From ad0923e9e034d8444561ce2fc0c2a212de0affd3 Mon Sep 17 00:00:00 2001 2 | From: Librae 3 | Date: Wed, 6 Jul 2016 18:20:52 +0800 4 | Subject: [PATCH] enable debug for OTA 5 | 6 | --- 7 | cores/esp8266/Updater.cpp | 49 +++++++-------------- 8 | .../ESP8266httpUpdate/src/ESP8266httpUpdate.cpp | 50 +++++++++++----------- 9 | .../ESP8266httpUpdate/src/ESP8266httpUpdate.h | 5 +++ 10 | 3 files changed, 45 insertions(+), 59 deletions(-) 11 | 12 | diff --git a/cores/esp8266/Updater.cpp b/cores/esp8266/Updater.cpp 13 | index 4764742..4c2c10e 100755 14 | --- a/cores/esp8266/Updater.cpp 15 | +++ b/cores/esp8266/Updater.cpp 16 | @@ -3,7 +3,9 @@ 17 | #include "eboot_command.h" 18 | #include "interrupts.h" 19 | 20 | -//#define DEBUG_UPDATER Serial 21 | +#ifndef DEBUG_UPDATER 22 | +#define DEBUG_UPDATER Serial 23 | +#endif 24 | 25 | extern "C" { 26 | #include "c_types.h" 27 | @@ -38,31 +40,23 @@ void UpdaterClass::_reset() { 28 | 29 | bool UpdaterClass::begin(size_t size, int command) { 30 | if(_size > 0){ 31 | -#ifdef DEBUG_UPDATER 32 | DEBUG_UPDATER.println("[begin] already running"); 33 | -#endif 34 | return false; 35 | } 36 | 37 | -#ifdef DEBUG_UPDATER 38 | if (command == U_SPIFFS) { 39 | DEBUG_UPDATER.println("[begin] Update SPIFFS."); 40 | } 41 | -#endif 42 | 43 | if(size == 0) { 44 | _error = UPDATE_ERROR_SIZE; 45 | -#ifdef DEBUG_UPDATER 46 | printError(DEBUG_UPDATER); 47 | -#endif 48 | return false; 49 | } 50 | 51 | if(!ESP.checkFlashConfig(false)) { 52 | _error = UPDATE_ERROR_FLASH_CONFIG; 53 | -#ifdef DEBUG_UPDATER 54 | printError(DEBUG_UPDATER); 55 | -#endif 56 | return false; 57 | } 58 | 59 | @@ -71,6 +65,8 @@ bool UpdaterClass::begin(size_t size, int command) { 60 | 61 | wifi_set_sleep_type(NONE_SLEEP_T); 62 | 63 | + DEBUG_UPDATER.printf("target size: %u\n\r", size); 64 | + 65 | uint32_t updateStartAddress = 0; 66 | if (command == U_FLASH) { 67 | //size of current sketch rounded to a sector 68 | @@ -82,7 +78,7 @@ bool UpdaterClass::begin(size_t size, int command) { 69 | //address where we will start writing the update 70 | updateStartAddress = updateEndAddress - roundedSize; 71 | 72 | -#ifdef DEBUG_UPDATER 73 | +#if 0 74 | DEBUG_UPDATER.printf("[begin] roundedSize: 0x%08X (%d)\n", roundedSize, roundedSize); 75 | DEBUG_UPDATER.printf("[begin] updateEndAddress: 0x%08X (%d)\n", updateEndAddress, updateEndAddress); 76 | DEBUG_UPDATER.printf("[begin] currentSketchSize: 0x%08X (%d)\n", currentSketchSize, currentSketchSize); 77 | @@ -91,9 +87,7 @@ bool UpdaterClass::begin(size_t size, int command) { 78 | //make sure that the size of both sketches is less than the total space (updateEndAddress) 79 | if(updateStartAddress < currentSketchSize) { 80 | _error = UPDATE_ERROR_SPACE; 81 | -#ifdef DEBUG_UPDATER 82 | printError(DEBUG_UPDATER); 83 | -#endif 84 | return false; 85 | } 86 | } 87 | @@ -102,9 +96,7 @@ bool UpdaterClass::begin(size_t size, int command) { 88 | } 89 | else { 90 | // unknown command 91 | -#ifdef DEBUG_UPDATER 92 | DEBUG_UPDATER.println("[begin] Unknown update command."); 93 | -#endif 94 | return false; 95 | } 96 | 97 | @@ -115,7 +107,7 @@ bool UpdaterClass::begin(size_t size, int command) { 98 | _buffer = new uint8_t[FLASH_SECTOR_SIZE]; 99 | _command = command; 100 | 101 | -#ifdef DEBUG_UPDATER 102 | +#if 0 103 | DEBUG_UPDATER.printf("[begin] _startAddress: 0x%08X (%d)\n", _startAddress, _startAddress); 104 | DEBUG_UPDATER.printf("[begin] _currentAddress: 0x%08X (%d)\n", _currentAddress, _currentAddress); 105 | DEBUG_UPDATER.printf("[begin] _size: 0x%08X (%d)\n", _size, _size); 106 | @@ -136,14 +128,12 @@ bool UpdaterClass::setMD5(const char * expected_md5){ 107 | 108 | bool UpdaterClass::end(bool evenIfRemaining){ 109 | if(_size == 0){ 110 | -#ifdef DEBUG_UPDATER 111 | DEBUG_UPDATER.println("no update"); 112 | -#endif 113 | return false; 114 | } 115 | 116 | if(hasError() || (!isFinished() && !evenIfRemaining)){ 117 | -#ifdef DEBUG_UPDATER 118 | +#if 0 119 | DEBUG_UPDATER.printf("premature end: res:%u, pos:%u/%u\n", getError(), progress(), _size); 120 | #endif 121 | 122 | @@ -162,21 +152,19 @@ bool UpdaterClass::end(bool evenIfRemaining){ 123 | if(_target_md5.length()) { 124 | if(_target_md5 != _md5.toString()){ 125 | _error = UPDATE_ERROR_MD5; 126 | -#ifdef DEBUG_UPDATER 127 | +#if 0 128 | DEBUG_UPDATER.printf("MD5 Failed: expected:%s, calculated:%s\n", _target_md5.c_str(), _md5.toString().c_str()); 129 | #endif 130 | _reset(); 131 | return false; 132 | } 133 | -#ifdef DEBUG_UPDATER 134 | +#if 0 135 | else DEBUG_UPDATER.printf("MD5 Success: %s\n", _target_md5.c_str()); 136 | #endif 137 | } 138 | 139 | if(!_verifyEnd()) { 140 | -#ifdef DEBUG_UPDATER 141 | printError(DEBUG_UPDATER); 142 | -#endif 143 | _reset(); 144 | return false; 145 | } 146 | @@ -189,12 +177,10 @@ bool UpdaterClass::end(bool evenIfRemaining){ 147 | ebcmd.args[2] = _size; 148 | eboot_command_write(&ebcmd); 149 | 150 | -#ifdef DEBUG_UPDATER 151 | - DEBUG_UPDATER.printf("Staged: address:0x%08X, size:0x%08X\n", _startAddress, _size); 152 | + DEBUG_UPDATER.printf("Staged: address: 0x%08x, size: %u\n\r", _startAddress, _size); 153 | } 154 | else if (_command == U_SPIFFS) { 155 | - DEBUG_UPDATER.printf("SPIFFS: address:0x%08X, size:0x%08X\n", _startAddress, _size); 156 | -#endif 157 | + DEBUG_UPDATER.printf("SPIFFS: address: 0x%08x, size: %u\n\r", _startAddress, _size); 158 | } 159 | 160 | _reset(); 161 | @@ -204,6 +190,7 @@ bool UpdaterClass::end(bool evenIfRemaining){ 162 | bool UpdaterClass::_writeBuffer(){ 163 | 164 | if(!_async) yield(); 165 | + DEBUG_UPDATER.printf("write 0x%08x\n\r", _currentAddress); 166 | bool result = ESP.flashEraseSector(_currentAddress/FLASH_SECTOR_SIZE); 167 | if(!_async) yield(); 168 | if (result) { 169 | @@ -214,9 +201,7 @@ bool UpdaterClass::_writeBuffer(){ 170 | if (!result) { 171 | _error = UPDATE_ERROR_WRITE; 172 | _currentAddress = (_startAddress + _size); 173 | -#ifdef DEBUG_UPDATER 174 | printError(DEBUG_UPDATER); 175 | -#endif 176 | return false; 177 | } 178 | _md5.add(_buffer, _bufferLen); 179 | @@ -312,9 +297,7 @@ size_t UpdaterClass::writeStream(Stream &data) { 180 | return 0; 181 | 182 | if(!_verifyHeader(data.peek())) { 183 | -#ifdef DEBUG_UPDATER 184 | printError(DEBUG_UPDATER); 185 | -#endif 186 | _reset(); 187 | return 0; 188 | } 189 | @@ -327,9 +310,7 @@ size_t UpdaterClass::writeStream(Stream &data) { 190 | if(toRead == 0) { //Timeout 191 | _error = UPDATE_ERROR_STREAM; 192 | _currentAddress = (_startAddress + _size); 193 | -#ifdef DEBUG_UPDATER 194 | printError(DEBUG_UPDATER); 195 | -#endif 196 | _reset(); 197 | return written; 198 | } 199 | @@ -362,9 +343,9 @@ void UpdaterClass::printError(Stream &out){ 200 | } else if(_error == UPDATE_ERROR_MD5){ 201 | out.println("MD5 Check Failed"); 202 | } else if(_error == UPDATE_ERROR_FLASH_CONFIG){ 203 | - out.printf("Flash config wrong real: %d IDE: %d\n", ESP.getFlashChipRealSize(), ESP.getFlashChipSize()); 204 | + out.printf("Flash config wrong real: %d IDE: %d\n\r", ESP.getFlashChipRealSize(), ESP.getFlashChipSize()); 205 | } else if(_error == UPDATE_ERROR_NEW_FLASH_CONFIG){ 206 | - out.printf("new Flash config wrong real: %d\n", ESP.getFlashChipRealSize()); 207 | + out.printf("new Flash config wrong real: %d\n\r", ESP.getFlashChipRealSize()); 208 | } else if(_error == UPDATE_ERROR_MAGIC_BYTE){ 209 | out.println("Magic byte is wrong, not 0xE9"); 210 | } else { 211 | diff --git a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp 212 | index c4dc841..524d2d2 100755 213 | --- a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp 214 | +++ b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp 215 | @@ -199,28 +199,28 @@ HTTPUpdateResult ESP8266HTTPUpdate::handleUpdate(HTTPClient& http, const String& 216 | int len = http.getSize(); 217 | 218 | if(code <= 0) { 219 | - DEBUG_HTTP_UPDATE("[httpUpdate] HTTP error: %s\n", http.errorToString(code).c_str()); 220 | + DEBUG_HTTP_UPDATE("[httpUpdate] HTTP error: %s\n\r", http.errorToString(code).c_str()); 221 | _lastError = code; 222 | http.end(); 223 | return HTTP_UPDATE_FAILED; 224 | } 225 | 226 | 227 | - DEBUG_HTTP_UPDATE("[httpUpdate] Header read fin.\n"); 228 | - DEBUG_HTTP_UPDATE("[httpUpdate] Server header:\n"); 229 | - DEBUG_HTTP_UPDATE("[httpUpdate] - code: %d\n", code); 230 | - DEBUG_HTTP_UPDATE("[httpUpdate] - len: %d\n", len); 231 | + DEBUG_HTTP_UPDATE("[httpUpdate] Header read fin.\n\r"); 232 | + DEBUG_HTTP_UPDATE("[httpUpdate] Server header:\n\r"); 233 | + DEBUG_HTTP_UPDATE("[httpUpdate] - code: %d\n\r", code); 234 | + DEBUG_HTTP_UPDATE("[httpUpdate] - len: %d\n\r", len); 235 | 236 | if(http.hasHeader("x-MD5")) { 237 | - DEBUG_HTTP_UPDATE("[httpUpdate] - MD5: %s\n", http.header("x-MD5").c_str()); 238 | + DEBUG_HTTP_UPDATE("[httpUpdate] - MD5: %s\n\r", http.header("x-MD5").c_str()); 239 | } 240 | 241 | - DEBUG_HTTP_UPDATE("[httpUpdate] ESP8266 info:\n"); 242 | - DEBUG_HTTP_UPDATE("[httpUpdate] - free Space: %d\n", ESP.getFreeSketchSpace()); 243 | - DEBUG_HTTP_UPDATE("[httpUpdate] - current Sketch Size: %d\n", ESP.getSketchSize()); 244 | + DEBUG_HTTP_UPDATE("[httpUpdate] ESP8266 info:\n\r"); 245 | + DEBUG_HTTP_UPDATE("[httpUpdate] - free Space: %d\n\r", ESP.getFreeSketchSpace()); 246 | + DEBUG_HTTP_UPDATE("[httpUpdate] - current Sketch Size: %d\n\r", ESP.getSketchSize()); 247 | 248 | if(currentVersion && currentVersion[0] != 0x00) { 249 | - DEBUG_HTTP_UPDATE("[httpUpdate] - current version: %s\n", currentVersion.c_str() ); 250 | + DEBUG_HTTP_UPDATE("[httpUpdate] - current version: %s\n\r", currentVersion.c_str() ); 251 | } 252 | 253 | switch(code) { 254 | @@ -230,12 +230,12 @@ HTTPUpdateResult ESP8266HTTPUpdate::handleUpdate(HTTPClient& http, const String& 255 | if(spiffs) { 256 | size_t spiffsSize = ((size_t) &_SPIFFS_end - (size_t) &_SPIFFS_start); 257 | if(len > (int) spiffsSize) { 258 | - DEBUG_HTTP_UPDATE("[httpUpdate] spiffsSize to low (%d) needed: %d\n", spiffsSize, len); 259 | + DEBUG_HTTP_UPDATE("[httpUpdate] spiffsSize to low (%d) needed: %d\n\r", spiffsSize, len); 260 | startUpdate = false; 261 | } 262 | } else { 263 | if(len > (int) ESP.getFreeSketchSpace()) { 264 | - DEBUG_HTTP_UPDATE("[httpUpdate] FreeSketchSpace to low (%d) needed: %d\n", ESP.getFreeSketchSpace(), len); 265 | + DEBUG_HTTP_UPDATE("[httpUpdate] FreeSketchSpace to low (%d) needed: %d\n\r", ESP.getFreeSketchSpace(), len); 266 | startUpdate = false; 267 | } 268 | } 269 | @@ -256,16 +256,16 @@ HTTPUpdateResult ESP8266HTTPUpdate::handleUpdate(HTTPClient& http, const String& 270 | 271 | if(spiffs) { 272 | command = U_SPIFFS; 273 | - DEBUG_HTTP_UPDATE("[httpUpdate] runUpdate spiffs...\n"); 274 | + DEBUG_HTTP_UPDATE("[httpUpdate] runUpdate spiffs...\n\r"); 275 | } else { 276 | command = U_FLASH; 277 | - DEBUG_HTTP_UPDATE("[httpUpdate] runUpdate flash...\n"); 278 | + DEBUG_HTTP_UPDATE("[httpUpdate] runUpdate flash...\n\r"); 279 | } 280 | 281 | if(!spiffs) { 282 | uint8_t buf[4]; 283 | if(tcp->peekBytes(&buf[0], 4) != 4) { 284 | - DEBUG_HTTP_UPDATE("[httpUpdate] peekBytes magic header failed\n"); 285 | + DEBUG_HTTP_UPDATE("[httpUpdate] peekBytes magic header failed\n\r"); 286 | _lastError = HTTP_UE_BIN_VERIFY_HEADER_FAILED; 287 | http.end(); 288 | return HTTP_UPDATE_FAILED; 289 | @@ -273,7 +273,7 @@ HTTPUpdateResult ESP8266HTTPUpdate::handleUpdate(HTTPClient& http, const String& 290 | 291 | // check for valid first magic byte 292 | if(buf[0] != 0xE9) { 293 | - DEBUG_HTTP_UPDATE("[httpUpdate] magic header not starts with 0xE9\n"); 294 | + DEBUG_HTTP_UPDATE("[httpUpdate] magic header not starts with 0xE9\n\r"); 295 | _lastError = HTTP_UE_BIN_VERIFY_HEADER_FAILED; 296 | http.end(); 297 | return HTTP_UPDATE_FAILED; 298 | @@ -284,7 +284,7 @@ HTTPUpdateResult ESP8266HTTPUpdate::handleUpdate(HTTPClient& http, const String& 299 | 300 | // check if new bin fits to SPI flash 301 | if(bin_flash_size > ESP.getFlashChipRealSize()) { 302 | - DEBUG_HTTP_UPDATE("[httpUpdate] magic header, new bin not fits SPI Flash\n"); 303 | + DEBUG_HTTP_UPDATE("[httpUpdate] magic header, new bin not fits SPI Flash\n\r"); 304 | _lastError = HTTP_UE_BIN_FOR_WRONG_FLASH; 305 | http.end(); 306 | return HTTP_UPDATE_FAILED; 307 | @@ -293,7 +293,7 @@ HTTPUpdateResult ESP8266HTTPUpdate::handleUpdate(HTTPClient& http, const String& 308 | 309 | if(runUpdate(*tcp, len, http.header("x-MD5"), command)) { 310 | ret = HTTP_UPDATE_OK; 311 | - DEBUG_HTTP_UPDATE("[httpUpdate] Update ok\n"); 312 | + DEBUG_HTTP_UPDATE("[httpUpdate] Update ok\n\r"); 313 | http.end(); 314 | 315 | if(_rebootOnUpdate) { 316 | @@ -302,13 +302,13 @@ HTTPUpdateResult ESP8266HTTPUpdate::handleUpdate(HTTPClient& http, const String& 317 | 318 | } else { 319 | ret = HTTP_UPDATE_FAILED; 320 | - DEBUG_HTTP_UPDATE("[httpUpdate] Update failed\n"); 321 | + DEBUG_HTTP_UPDATE("[httpUpdate] Update failed\n\r"); 322 | } 323 | } 324 | } else { 325 | _lastError = HTTP_UE_SERVER_NOT_REPORT_SIZE; 326 | ret = HTTP_UPDATE_FAILED; 327 | - DEBUG_HTTP_UPDATE("[httpUpdate] Content-Length is 0 or not set by Server?!\n"); 328 | + DEBUG_HTTP_UPDATE("[httpUpdate] Content-Length is 0 or not set by Server?!\n\r"); 329 | } 330 | break; 331 | case HTTP_CODE_NOT_MODIFIED: 332 | @@ -326,7 +326,7 @@ HTTPUpdateResult ESP8266HTTPUpdate::handleUpdate(HTTPClient& http, const String& 333 | default: 334 | _lastError = HTTP_UE_SERVER_WRONG_HTTP_CODE; 335 | ret = HTTP_UPDATE_FAILED; 336 | - DEBUG_HTTP_UPDATE("[httpUpdate] HTTP Code is (%d)\n", code); 337 | + DEBUG_HTTP_UPDATE("[httpUpdate] HTTP Code is (%d)\n\r", code); 338 | //http.writeToStream(&Serial1); 339 | break; 340 | } 341 | @@ -351,14 +351,14 @@ bool ESP8266HTTPUpdate::runUpdate(Stream& in, uint32_t size, String md5, int com 342 | _lastError = Update.getError(); 343 | Update.printError(error); 344 | error.trim(); // remove line ending 345 | - DEBUG_HTTP_UPDATE("[httpUpdate] Update.begin failed! (%s)\n", error.c_str()); 346 | + DEBUG_HTTP_UPDATE("[httpUpdate] Update.begin failed! (%s)\n\r", error.c_str()); 347 | return false; 348 | } 349 | 350 | if(md5.length()) { 351 | if(!Update.setMD5(md5.c_str())) { 352 | _lastError = HTTP_UE_SERVER_FAULTY_MD5; 353 | - DEBUG_HTTP_UPDATE("[httpUpdate] Update.setMD5 failed! (%s)\n", md5.c_str()); 354 | + DEBUG_HTTP_UPDATE("[httpUpdate] Update.setMD5 failed! (%s)\n\r", md5.c_str()); 355 | return false; 356 | } 357 | } 358 | @@ -367,7 +367,7 @@ bool ESP8266HTTPUpdate::runUpdate(Stream& in, uint32_t size, String md5, int com 359 | _lastError = Update.getError(); 360 | Update.printError(error); 361 | error.trim(); // remove line ending 362 | - DEBUG_HTTP_UPDATE("[httpUpdate] Update.writeStream failed! (%s)\n", error.c_str()); 363 | + DEBUG_HTTP_UPDATE("[httpUpdate] Update.writeStream failed! (%s)\n\r", error.c_str()); 364 | return false; 365 | } 366 | 367 | @@ -375,7 +375,7 @@ bool ESP8266HTTPUpdate::runUpdate(Stream& in, uint32_t size, String md5, int com 368 | _lastError = Update.getError(); 369 | Update.printError(error); 370 | error.trim(); // remove line ending 371 | - DEBUG_HTTP_UPDATE("[httpUpdate] Update.end failed! (%s)\n", error.c_str()); 372 | + DEBUG_HTTP_UPDATE("[httpUpdate] Update.end failed! (%s)\n\r", error.c_str()); 373 | return false; 374 | } 375 | 376 | diff --git a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h 377 | index af6931b..e9352e8 100755 378 | --- a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h 379 | +++ b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h 380 | @@ -32,11 +32,16 @@ 381 | #include 382 | #include 383 | 384 | +#if 0 385 | #ifdef DEBUG_ESP_HTTP_UPDATE 386 | #ifdef DEBUG_ESP_PORT 387 | #define DEBUG_HTTP_UPDATE(...) DEBUG_ESP_PORT.printf( __VA_ARGS__ ) 388 | #endif 389 | #endif 390 | +#else 391 | +#define DEBUG_ESP_HTTP_UPDATE 392 | +#define DEBUG_HTTP_UPDATE(...) Serial.printf( __VA_ARGS__ ) 393 | +#endif 394 | 395 | #ifndef DEBUG_HTTP_UPDATE 396 | #define DEBUG_HTTP_UPDATE(...) 397 | -- 398 | 1.9.1 399 | 400 | -------------------------------------------------------------------------------- /patch/0001-fix-newlines.patch: -------------------------------------------------------------------------------- 1 | From 27f30b6dfdd31decf6896e6cb10531dd2f250c4f Mon Sep 17 00:00:00 2001 2 | From: Librae 3 | Date: Sat, 24 Sep 2016 00:30:19 +0800 4 | Subject: [PATCH] fix newlines 5 | 6 | --- 7 | libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp | 44 +++++++++++++------------- 8 | 1 file changed, 22 insertions(+), 22 deletions(-) 9 | 10 | diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp 11 | index 68e5845..9c78d98 100755 12 | --- a/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp 13 | +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp 14 | @@ -55,13 +55,13 @@ wl_status_t ESP8266WiFiMulti::run(void) { 15 | uint8 bestBSSID[6]; 16 | int32_t bestChannel; 17 | 18 | - DEBUG_WIFI_MULTI("[WIFI] scan done\n"); 19 | + DEBUG_WIFI_MULTI("[WIFI] scan done\n\r"); 20 | delay(0); 21 | 22 | if(scanResult <= 0) { 23 | - DEBUG_WIFI_MULTI("[WIFI] no networks found\n"); 24 | + DEBUG_WIFI_MULTI("[WIFI] no networks found\n\r"); 25 | } else { 26 | - DEBUG_WIFI_MULTI("[WIFI] %d networks found\n", scanResult); 27 | + DEBUG_WIFI_MULTI("[WIFI] %d networks found\n\r", scanResult); 28 | for(int8_t i = 0; i < scanResult; ++i) { 29 | 30 | String ssid_scan; 31 | @@ -97,7 +97,7 @@ wl_status_t ESP8266WiFiMulti::run(void) { 32 | DEBUG_WIFI_MULTI(" "); 33 | } 34 | 35 | - DEBUG_WIFI_MULTI(" %d: [%d][%02X:%02X:%02X:%02X:%02X:%02X] %s (%d) %c\n", i, chan_scan, BSSID_scan[0], BSSID_scan[1], BSSID_scan[2], BSSID_scan[3], BSSID_scan[4], BSSID_scan[5], ssid_scan.c_str(), rssi_scan, (sec_scan == ENC_TYPE_NONE) ? ' ' : '*'); 36 | + DEBUG_WIFI_MULTI(" %d: [%d][%02X:%02X:%02X:%02X:%02X:%02X] %s (%d) %c\n\r", i, chan_scan, BSSID_scan[0], BSSID_scan[1], BSSID_scan[2], BSSID_scan[3], BSSID_scan[4], BSSID_scan[5], ssid_scan.c_str(), rssi_scan, (sec_scan == ENC_TYPE_NONE) ? ' ' : '*'); 37 | delay(0); 38 | } 39 | } 40 | @@ -105,11 +105,11 @@ wl_status_t ESP8266WiFiMulti::run(void) { 41 | // clean up ram 42 | WiFi.scanDelete(); 43 | 44 | - DEBUG_WIFI_MULTI("\n\n"); 45 | + DEBUG_WIFI_MULTI("\n\r"); 46 | delay(0); 47 | 48 | if(bestNetwork.ssid) { 49 | - DEBUG_WIFI_MULTI("[WIFI] Connecting BSSID: %02X:%02X:%02X:%02X:%02X:%02X SSID: %s Channal: %d (%d)\n", bestBSSID[0], bestBSSID[1], bestBSSID[2], bestBSSID[3], bestBSSID[4], bestBSSID[5], bestNetwork.ssid, bestChannel, bestNetworkDb); 50 | + DEBUG_WIFI_MULTI("[WIFI] Connecting BSSID: %02X:%02X:%02X:%02X:%02X:%02X SSID: %s Channal: %d (%d)\n\r", bestBSSID[0], bestBSSID[1], bestBSSID[2], bestBSSID[3], bestBSSID[4], bestBSSID[5], bestNetwork.ssid, bestChannel, bestNetworkDb); 51 | 52 | WiFi.begin(bestNetwork.ssid, bestNetwork.passphrase, bestChannel, bestBSSID); 53 | status = WiFi.status(); 54 | @@ -126,32 +126,32 @@ wl_status_t ESP8266WiFiMulti::run(void) { 55 | case WL_CONNECTED: 56 | ip = WiFi.localIP(); 57 | mac = WiFi.BSSID(); 58 | - DEBUG_WIFI_MULTI("[WIFI] Connecting done.\n"); 59 | - DEBUG_WIFI_MULTI("[WIFI] SSID: %s\n", WiFi.SSID().c_str()); 60 | - DEBUG_WIFI_MULTI("[WIFI] IP: %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]); 61 | - DEBUG_WIFI_MULTI("[WIFI] MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); 62 | - DEBUG_WIFI_MULTI("[WIFI] Channel: %d\n", WiFi.channel()); 63 | + DEBUG_WIFI_MULTI("[WIFI] Connecting done.\n\r"); 64 | + DEBUG_WIFI_MULTI("[WIFI] SSID: %s\n\r", WiFi.SSID().c_str()); 65 | + DEBUG_WIFI_MULTI("[WIFI] IP: %d.%d.%d.%d\n\r", ip[0], ip[1], ip[2], ip[3]); 66 | + DEBUG_WIFI_MULTI("[WIFI] MAC: %02X:%02X:%02X:%02X:%02X:%02X\n\r", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); 67 | + DEBUG_WIFI_MULTI("[WIFI] Channel: %d\n\r", WiFi.channel()); 68 | break; 69 | case WL_NO_SSID_AVAIL: 70 | - DEBUG_WIFI_MULTI("[WIFI] Connecting Failed AP not found.\n"); 71 | + DEBUG_WIFI_MULTI("[WIFI] Connecting Failed AP not found.\n\r"); 72 | break; 73 | case WL_CONNECT_FAILED: 74 | - DEBUG_WIFI_MULTI("[WIFI] Connecting Failed.\n"); 75 | + DEBUG_WIFI_MULTI("[WIFI] Connecting Failed.\n\r"); 76 | break; 77 | default: 78 | - DEBUG_WIFI_MULTI("[WIFI] Connecting Failed (%d).\n", status); 79 | + DEBUG_WIFI_MULTI("[WIFI] Connecting Failed (%d).\n\r", status); 80 | break; 81 | } 82 | #endif 83 | } else { 84 | - DEBUG_WIFI_MULTI("[WIFI] no matching wifi found!\n"); 85 | + DEBUG_WIFI_MULTI("[WIFI] no matching wifi found!\n\r"); 86 | } 87 | } else { 88 | // start scan 89 | - DEBUG_WIFI_MULTI("[WIFI] delete old wifi config...\n"); 90 | + DEBUG_WIFI_MULTI("[WIFI] delete old wifi config...\n\r"); 91 | WiFi.disconnect(); 92 | 93 | - DEBUG_WIFI_MULTI("[WIFI] start scan\n"); 94 | + DEBUG_WIFI_MULTI("[WIFI] start scan\n\r"); 95 | // scan wifi async mode 96 | WiFi.scanNetworks(true); 97 | } 98 | @@ -167,34 +167,34 @@ bool ESP8266WiFiMulti::APlistAdd(const char* ssid, const char *passphrase) { 99 | 100 | if(!ssid || *ssid == 0x00 || strlen(ssid) > 31) { 101 | // fail SSID to long or missing! 102 | - DEBUG_WIFI_MULTI("[WIFI][APlistAdd] no ssid or ssid to long\n"); 103 | + DEBUG_WIFI_MULTI("[WIFI][APlistAdd] no ssid or ssid to long\n\r"); 104 | return false; 105 | } 106 | 107 | if(passphrase && strlen(passphrase) > 63) { 108 | // fail passphrase to long! 109 | - DEBUG_WIFI_MULTI("[WIFI][APlistAdd] passphrase to long\n"); 110 | + DEBUG_WIFI_MULTI("[WIFI][APlistAdd] passphrase to long\n\r"); 111 | return false; 112 | } 113 | 114 | newAP.ssid = strdup(ssid); 115 | 116 | if(!newAP.ssid) { 117 | - DEBUG_WIFI_MULTI("[WIFI][APlistAdd] fail newAP.ssid == 0\n"); 118 | + DEBUG_WIFI_MULTI("[WIFI][APlistAdd] fail newAP.ssid == 0\n\r"); 119 | return false; 120 | } 121 | 122 | if(passphrase && *passphrase != 0x00) { 123 | newAP.passphrase = strdup(passphrase); 124 | if(!newAP.passphrase) { 125 | - DEBUG_WIFI_MULTI("[WIFI][APlistAdd] fail newAP.passphrase == 0\n"); 126 | + DEBUG_WIFI_MULTI("[WIFI][APlistAdd] fail newAP.passphrase == 0\n\r"); 127 | free(newAP.ssid); 128 | return false; 129 | } 130 | } 131 | 132 | APlist.push_back(newAP); 133 | - DEBUG_WIFI_MULTI("[WIFI][APlistAdd] add SSID: %s\n", newAP.ssid); 134 | + DEBUG_WIFI_MULTI("[WIFI][APlistAdd] add SSID: %s\n\r", newAP.ssid); 135 | return true; 136 | } 137 | 138 | -- 139 | 1.9.1 140 | 141 | -------------------------------------------------------------------------------- /patch/0001-increase-mqtt-msg-size-to-256.patch: -------------------------------------------------------------------------------- 1 | From ea4d8f29fbea8a4865a5882232945272d5f0a90a Mon Sep 17 00:00:00 2001 2 | From: Librae 3 | Date: Sat, 16 Apr 2016 17:16:53 +0800 4 | Subject: [PATCH] increase mqtt msg size to 256 5 | 6 | --- 7 | src/PubSubClient.h | 2 +- 8 | 1 file changed, 1 insertion(+), 1 deletion(-) 9 | 10 | diff --git a/src/PubSubClient.h b/src/PubSubClient.h 11 | index be4bd67..10cb784 100755 12 | --- a/src/PubSubClient.h 13 | +++ b/src/PubSubClient.h 14 | @@ -23,7 +23,7 @@ 15 | 16 | // MQTT_MAX_PACKET_SIZE : Maximum packet size 17 | #ifndef MQTT_MAX_PACKET_SIZE 18 | -#define MQTT_MAX_PACKET_SIZE 128 19 | +#define MQTT_MAX_PACKET_SIZE 256 20 | #endif 21 | 22 | // MQTT_KEEPALIVE : keepAlive interval in Seconds 23 | -- 24 | 1.9.1 25 | 26 | -------------------------------------------------------------------------------- /platformio.ini: -------------------------------------------------------------------------------- 1 | # 2 | # Project Configuration File 3 | # 4 | # A detailed documentation with the EXAMPLES is located here: 5 | # http://docs.platformio.org/en/latest/projectconf.html 6 | # 7 | 8 | # A sign `#` at the beginning of the line indicates a comment 9 | # Comment lines are ignored. 10 | 11 | # Simple and base environment 12 | # [env:mybaseenv] 13 | # platform = %INSTALLED_PLATFORM_NAME_HERE% 14 | # framework = 15 | # board = 16 | # 17 | # Automatic targets - enable auto-uploading 18 | # targets = upload 19 | 20 | # 4m1m 21 | [env:neurite] 22 | platform = espressif8266 23 | framework = arduino 24 | board = neurite 25 | upload_speed = 921600 26 | -------------------------------------------------------------------------------- /prebuild/firmware.bin.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkgo/neurite/ed3504ef2a637ba1986b1d1fbdedaa6434e4d1a9/prebuild/firmware.bin.gz -------------------------------------------------------------------------------- /prebuild/firmware.dev.bin.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkgo/neurite/ed3504ef2a637ba1986b1d1fbdedaa6434e4d1a9/prebuild/firmware.dev.bin.gz -------------------------------------------------------------------------------- /prebuild/spiffs.1m.bin.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkgo/neurite/ed3504ef2a637ba1986b1d1fbdedaa6434e4d1a9/prebuild/spiffs.1m.bin.gz -------------------------------------------------------------------------------- /prebuild/spiffs.64k.bin.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkgo/neurite/ed3504ef2a637ba1986b1d1fbdedaa6434e4d1a9/prebuild/spiffs.64k.bin.gz -------------------------------------------------------------------------------- /src/neurite.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2016 Linkgo LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #include 26 | 27 | #include "neurite_utils.h" 28 | 29 | #include 30 | #ifdef NEURITE_ENABLE_WIFIMULTI 31 | #include 32 | #endif 33 | #include 34 | #include 35 | #include 36 | #ifdef NEURITE_ENABLE_MDNS 37 | #include 38 | #endif 39 | #ifdef NEURITE_ENABLE_DNSPORTAL 40 | #include 41 | #endif 42 | #include 43 | #include 44 | #include 45 | #include "FS.h" 46 | 47 | extern "C" { 48 | #include "osapi.h" 49 | #include "ets_sys.h" 50 | #include "user_interface.h" 51 | } 52 | 53 | #include "neurite_priv.h" 54 | 55 | /* global */ 56 | extern struct neurite_data_s g_nd; 57 | 58 | /* static */ 59 | static struct cmd_parser_s g_cp; 60 | static char cmd_buf[NEURITE_CMD_BUF_SIZE]; 61 | static bool b_cfg_ready; 62 | 63 | static Ticker ticker_led; 64 | static Ticker ticker_cmd; 65 | static Ticker ticker_mon; 66 | static Ticker ticker_but; 67 | static Ticker ticker_reboot; 68 | static ESP8266WebServer *server; 69 | static File fsUploadFile; 70 | #ifdef NEURITE_ENABLE_WIFIMULTI 71 | static ESP8266WiFiMulti WiFiMulti; 72 | #endif 73 | static char cfg_buf[NEURITE_CFG_SIZE]; 74 | 75 | const char STR_READY[] PROGMEM = "neurite ready"; 76 | 77 | static void reboot(struct neurite_data_s *nd); 78 | 79 | enum { 80 | WORKER_ST_0 = 0, 81 | WORKER_ST_1, 82 | WORKER_ST_2, 83 | WORKER_ST_3, 84 | WORKER_ST_4 85 | }; 86 | static int worker_st = WORKER_ST_0; 87 | 88 | static inline void update_worker_state(int st) 89 | { 90 | log_dbg("-> WORKER_ST_%d\n\r", st); 91 | worker_st = st; 92 | } 93 | 94 | static void file_dump(const char *file) 95 | { 96 | if (!file) { 97 | log_warn("invalid pointer!\n\r"); 98 | return; 99 | } 100 | File configFile = SPIFFS.open(file, "r"); 101 | if (!configFile) { 102 | log_err("open failed\n\r"); 103 | return; 104 | } 105 | log_dbg("%s:\n\r", file); 106 | while (configFile.available()) 107 | LOG_SERIAL.write(configFile.read()); 108 | LOG_SERIAL.println(); 109 | configFile.close(); 110 | } 111 | 112 | static void ota_hold(void) 113 | { 114 | struct neurite_data_s *nd = &g_nd; 115 | #ifdef NEURITE_ENABLE_USER 116 | neurite_user_hold(); 117 | #endif 118 | stop_ticker_but(nd); 119 | stop_ticker_mon(nd); 120 | stop_ticker_led(nd); 121 | stop_ticker_cmd(nd); 122 | } 123 | 124 | static void ota_release(void) 125 | { 126 | struct neurite_data_s *nd = &g_nd; 127 | start_ticker_cmd(nd); 128 | start_ticker_led_breath(nd); 129 | start_ticker_mon(nd); 130 | start_ticker_but(nd); 131 | } 132 | 133 | static int ota_over_http(const char *url) 134 | { 135 | if (!url) { 136 | log_err("invalid url\n\r"); 137 | return -1; 138 | } 139 | CMD_SERIAL.print("ota: "); 140 | CMD_SERIAL.println(url); 141 | 142 | ota_hold(); 143 | t_httpUpdate_return ret; 144 | ret = ESPhttpUpdate.update(url); 145 | 146 | switch (ret) { 147 | case HTTP_UPDATE_FAILED: 148 | log_err("failed\n\r"); 149 | break; 150 | 151 | case HTTP_UPDATE_NO_UPDATES: 152 | log_warn("no updates\n\r"); 153 | break; 154 | 155 | case HTTP_UPDATE_OK: 156 | log_info("ok\n\r"); 157 | break; 158 | } 159 | ota_release(); 160 | return ret; 161 | } 162 | 163 | static int otafs_over_http(const char *url) 164 | { 165 | if (!url) { 166 | log_err("invalid url\n\r"); 167 | return -1; 168 | } 169 | CMD_SERIAL.print("otafs: "); 170 | CMD_SERIAL.println(url); 171 | 172 | ota_hold(); 173 | t_httpUpdate_return ret; 174 | ret = ESPhttpUpdate.updateSpiffs(url); 175 | 176 | switch (ret) { 177 | case HTTP_UPDATE_FAILED: 178 | log_err("failed\n\r"); 179 | break; 180 | 181 | case HTTP_UPDATE_NO_UPDATES: 182 | log_warn("no updates\n\r"); 183 | break; 184 | 185 | case HTTP_UPDATE_OK: 186 | log_info("ok\n\r"); 187 | break; 188 | } 189 | ota_release(); 190 | return ret; 191 | } 192 | 193 | static void ticker_led_breath(void) 194 | { 195 | static int val = 1023; 196 | static int state = 0; 197 | if (val >= 1023) 198 | state = 1; 199 | else if (val <= 523) 200 | state = 0; 201 | else 202 | ; 203 | if (state) 204 | val -= 10; 205 | else 206 | val += 10; 207 | analogWrite(NEURITE_LED, val); 208 | } 209 | 210 | static void ticker_led_blink(void) 211 | { 212 | static int val = 1023; 213 | analogWrite(NEURITE_LED, val); 214 | val = (val == 1023) ? 500 : 1023; 215 | } 216 | 217 | static bool cfg_get(const char *str, char *buf, size_t size) 218 | { 219 | struct neurite_data_s *nd = &g_nd; 220 | if (!buf || !str) { 221 | log_warn("invalid pointer!\n\r"); 222 | return false; 223 | } 224 | 225 | StaticJsonBuffer json_buf; 226 | JsonObject& json = json_buf.parseObject((const char *)nd->cfg.json_buf); 227 | if (!json.success()) { 228 | log_err("parse failed\n\r"); 229 | return false; 230 | } 231 | const char *p = json[str]; 232 | if (p) { 233 | strncpy(buf, p, size); 234 | //log_dbg("'%s': %s\n\r", str, p); 235 | return true; 236 | } else { 237 | log_warn("no cfg '%s' found\n\r", str, p); 238 | return false; 239 | } 240 | } 241 | 242 | static bool cfg_set(const char *str, const char *buf, size_t size) 243 | { 244 | struct neurite_data_s *nd = &g_nd; 245 | if (!buf || !str) { 246 | log_warn("invalid pointer!\n\r"); 247 | return false; 248 | } 249 | StaticJsonBuffer json_buf; 250 | JsonObject& json = json_buf.parseObject((const char *)nd->cfg.json_buf); 251 | if (!json.success()) { 252 | log_err("parse failed\n\r"); 253 | return false; 254 | } 255 | json[str] = buf; 256 | json.printTo(nd->cfg.json_buf, NEURITE_CFG_SIZE); 257 | //log_dbg("'%s': %s\n\r", str, buf); 258 | return true; 259 | } 260 | 261 | static bool cfg_save(const char *file) 262 | { 263 | struct neurite_data_s *nd = &g_nd; 264 | if (!file) { 265 | log_warn("invalid pointer!\n\r"); 266 | return false; 267 | } 268 | StaticJsonBuffer json_buf; 269 | JsonObject& json = json_buf.parseObject((const char *)nd->cfg.json_buf); 270 | if (!json.success()) { 271 | log_err("parse failed\n\r"); 272 | return false; 273 | } 274 | File configFile = SPIFFS.open(file, "w"); 275 | if (!configFile) { 276 | log_err("open failed\n\r"); 277 | return false; 278 | } else { 279 | log_dbg("open %s successfully\n\r", file); 280 | } 281 | size_t size = json.printTo(configFile); 282 | log_dbg("wrote %d bytes\n\r", size); 283 | configFile.close(); 284 | file_dump(file); 285 | return true; 286 | } 287 | 288 | static bool cfg_load(const char *file) 289 | { 290 | struct neurite_data_s *nd = &g_nd; 291 | if (!file) { 292 | log_warn("invalid pointer!\n\r"); 293 | return false; 294 | } 295 | File configFile = SPIFFS.open(file, "r"); 296 | if (!configFile) { 297 | log_err("open failed\n\r"); 298 | return false; 299 | } 300 | size_t size = configFile.size(); 301 | if (size > NEURITE_CFG_SIZE) { 302 | log_err("file too large\n\r"); 303 | configFile.close(); 304 | return false; 305 | } 306 | __bzero(nd->cfg.json_buf, NEURITE_CFG_SIZE); 307 | size = configFile.readBytes(nd->cfg.json_buf, size); 308 | log_info("load %s size: %d\n\r", file, size); 309 | configFile.close(); 310 | cfg_dump(); 311 | return true; 312 | } 313 | 314 | static bool cfg_dump(void) 315 | { 316 | struct neurite_data_s *nd = &g_nd; 317 | StaticJsonBuffer json_buf; 318 | JsonObject& json = json_buf.parseObject((const char *)nd->cfg.json_buf); 319 | if (!json.success()) { 320 | log_err("parse failed\n\r"); 321 | return false; 322 | } 323 | log_dbg(""); 324 | json.printTo(LOG_SERIAL); 325 | LOG_SERIAL.println(); 326 | return true; 327 | } 328 | 329 | static bool cfg_validate(struct neurite_data_s *nd) 330 | { 331 | log_dbg("in\n\r"); 332 | char ssid[NEURITE_SSID_LEN] = {0}; 333 | nd->cfg.get("ssid", ssid, NEURITE_SSID_LEN); 334 | /* FIXME How if the real SSID just equals to SSID1? */ 335 | if (strcmp(ssid, SSID1) == 0) { 336 | log_warn("no ssid cfg\n\r"); 337 | return false; 338 | } 339 | 340 | log_dbg("out\n\r"); 341 | return true; 342 | } 343 | 344 | static void wifi_connect(struct neurite_data_s *nd) 345 | { 346 | char ssid[NEURITE_SSID_LEN] = {0}; 347 | char psk[NEURITE_PSK_LEN] = {0}; 348 | nd->cfg.get("ssid", ssid, NEURITE_SSID_LEN); 349 | nd->cfg.get("psk", psk, NEURITE_PSK_LEN); 350 | log_dbg("Connecting to %s <%s>\n\r", ssid, psk); 351 | WiFi.mode(WIFI_STA); 352 | WiFi.hostname(nd->uid); 353 | #ifdef NEURITE_ENABLE_WIFIMULTI 354 | WiFiMulti.addAP(ssid, psk); 355 | WiFiMulti.addAP(SSID2, PSK2); 356 | #else 357 | WiFi.begin(ssid, psk); 358 | #endif 359 | } 360 | 361 | static inline bool wifi_check_status(struct neurite_data_s *nd) 362 | { 363 | return (WiFi.status() == WL_CONNECTED); 364 | } 365 | 366 | static bool config_process(struct neurite_data_s *nd, char *token, char *msg, uint32_t size) 367 | { 368 | char value[NEURITE_CFG_ITEM_LEN]; 369 | if (token == NULL) { 370 | log_dbg("hit config, nothing\n\r"); 371 | } else { 372 | log_dbg("hit config: %s\n\r", token); 373 | __bzero(value, NEURITE_CFG_ITEM_LEN); 374 | strncpy(value, msg, NEURITE_CFG_ITEM_LEN); 375 | nd->cfg.set(token, value, NEURITE_CFG_ITEM_LEN); 376 | } 377 | nd->cfg.save(NEURITE_CFG_PATH); 378 | return true; 379 | } 380 | 381 | static void mqtt_callback(char *topic, byte *payload, unsigned int length) 382 | { 383 | struct neurite_data_s *nd = &g_nd; 384 | log_dbg("topic (%d): %s\n\r", strlen(topic), topic); 385 | log_dbg("data (%d): ", length); 386 | for (int i = 0; i < length; i++) 387 | LOG_SERIAL.print((char)payload[i]); 388 | LOG_SERIAL.println(); 389 | if (strncmp(topic, nd->topic_private, strlen(nd->topic_private) - 2) == 0) { 390 | char *subtopic = topic + strlen(nd->topic_private) - 2; 391 | char *token = NULL; 392 | token = strtok(subtopic, "/"); 393 | if (token == NULL) { 394 | log_warn("no subtopic, ignore\n\r"); 395 | } else if (strcmp(token, "config") == 0) { 396 | token = strtok(NULL, "/"); 397 | char *msg = (char *)malloc(MQTT_MSG_LEN + 1); 398 | __bzero(msg, sizeof(msg)); 399 | for (int i = 0; i < length; i++) 400 | msg[i] = payload[i]; 401 | msg[length] = '\0'; 402 | config_process(nd, token, msg, length); 403 | free(msg); 404 | } else if (strcmp(token, "ota") == 0) { 405 | log_dbg("hit ota\n\r"); 406 | char url[MQTT_MSG_LEN]; 407 | __bzero(url, sizeof(url)); 408 | for (int i = 0; i < length; i++) 409 | url[i] = payload[i]; 410 | ota_over_http(url); 411 | } else if (strcmp(token, "otafs") == 0) { 412 | log_dbg("hit otafs\n\r"); 413 | char url[MQTT_MSG_LEN]; 414 | __bzero(url, sizeof(url)); 415 | for (int i = 0; i < length; i++) 416 | url[i] = payload[i]; 417 | otafs_over_http(url); 418 | } else if (strcmp(token, "reboot") == 0) { 419 | reboot(nd); 420 | } else { 421 | log_warn("unsupported %s, leave to user\n\r", token); 422 | } 423 | } 424 | char topic_from[MQTT_TOPIC_LEN] = {0}; 425 | nd->cfg.get("topic_from", topic_from, MQTT_TOPIC_LEN); 426 | if (strcmp(topic, topic_from) == 0) { 427 | for (int i = 0; i < length; i++) 428 | CMD_SERIAL.print((char)payload[i]); 429 | /* FIXME here follows '\r' and '\n' */ 430 | CMD_SERIAL.println(); 431 | } 432 | #ifdef NEURITE_ENABLE_USER 433 | neurite_user_mqtt(topic, payload, length); 434 | #endif 435 | } 436 | 437 | static inline bool mqtt_check_status(struct neurite_data_s *nd) 438 | { 439 | return mqtt_cli.connected(); 440 | } 441 | 442 | static void mqtt_config(struct neurite_data_s *nd) 443 | { 444 | mqtt_cli.setServer(MQTT_SERVER, 1883); 445 | mqtt_cli.setCallback(mqtt_callback); 446 | } 447 | 448 | static void mqtt_connect(struct neurite_data_s *nd) 449 | { 450 | mqtt_cli.connect(nd->uid); 451 | } 452 | 453 | static void ticker_monitor_task(struct neurite_data_s *nd) 454 | { 455 | nd->wifi_connected = wifi_check_status(nd); 456 | nd->mqtt_connected = mqtt_check_status(nd); 457 | if (!nd->wifi_connected && worker_st >= WORKER_ST_2) { 458 | log_warn("WiFi disconnected\n\r"); 459 | update_worker_state(WORKER_ST_0); 460 | } 461 | if (!nd->mqtt_connected && worker_st >= WORKER_ST_4) { 462 | log_warn("MQTT disconnected\n\r"); 463 | update_worker_state(WORKER_ST_0); 464 | } 465 | } 466 | 467 | static void button_release_handler(struct neurite_data_s *nd, int dts) 468 | { 469 | log_dbg("button pressed for %d ms\n\r", dts); 470 | #ifdef NEURITE_ENABLE_USER 471 | neurite_user_button(dts); 472 | #endif 473 | } 474 | 475 | static void button_hold_handler(struct neurite_data_s *nd, int dts) 476 | { 477 | if (dts > 5000) { 478 | if (SPIFFS.remove(NEURITE_CFG_PATH)) { 479 | log_info("%s removed\n\r", NEURITE_CFG_PATH); 480 | reboot(nd); 481 | } else { 482 | log_err("%s failed to remove\n\r", NEURITE_CFG_PATH); 483 | } 484 | } 485 | } 486 | 487 | static void ticker_button_task(struct neurite_data_s *nd) 488 | { 489 | static int ts = 0; 490 | static int r_curr = HIGH; 491 | static int r_prev = HIGH; 492 | int dts; 493 | r_curr = digitalRead(NEURITE_BUTTON); 494 | if ((r_curr == LOW) && (r_prev == HIGH)) { 495 | ts = millis(); 496 | r_prev = r_curr; 497 | } else { 498 | if (r_prev == LOW) { 499 | dts = millis() - ts; 500 | r_prev = r_curr; 501 | if (r_curr == HIGH) 502 | button_release_handler(nd, dts); 503 | else 504 | button_hold_handler(nd, dts); 505 | } 506 | } 507 | } 508 | 509 | inline void stop_ticker_led(struct neurite_data_s *nd) 510 | { 511 | ticker_led.detach(); 512 | } 513 | inline void start_ticker_led_breath(struct neurite_data_s *nd) 514 | { 515 | ticker_led.detach(); 516 | stop_ticker_led(nd); 517 | ticker_led.attach_ms(50, ticker_led_breath); 518 | } 519 | inline void start_ticker_led_blink(struct neurite_data_s *nd) 520 | { 521 | ticker_mon.detach(); 522 | stop_ticker_led(nd); 523 | ticker_led.attach_ms(50, ticker_led_blink); 524 | } 525 | inline void stop_ticker_mon(struct neurite_data_s *nd) 526 | { 527 | ticker_mon.detach(); 528 | } 529 | inline void start_ticker_mon(struct neurite_data_s *nd) 530 | { 531 | ticker_mon.detach(); 532 | stop_ticker_mon(nd); 533 | ticker_mon.attach_ms(100, ticker_monitor_task, nd); 534 | } 535 | inline void stop_ticker_but(struct neurite_data_s *nd) 536 | { 537 | ticker_but.detach(); 538 | } 539 | inline void start_ticker_but(struct neurite_data_s *nd) 540 | { 541 | ticker_but.detach(); 542 | stop_ticker_but(nd); 543 | ticker_but.attach_ms(50, ticker_button_task, nd); 544 | } 545 | 546 | static void cmd_completed_cb(struct cmd_parser_s *cp) 547 | { 548 | struct neurite_data_s *nd = &g_nd; 549 | dbg_assert(cp); 550 | if (cp->data_len > 0) { 551 | if (nd->mqtt_connected) { 552 | char topic_to[MQTT_TOPIC_LEN] = {0}; 553 | nd->cfg.get("topic_to", topic_to, MQTT_TOPIC_LEN); 554 | mqtt_cli.publish(topic_to, cp->buf); 555 | } 556 | log_dbg("msg %slaunched(len %d): %s\n\r", 557 | nd->mqtt_connected?"":"not ", cp->data_len, cp->buf); 558 | } 559 | __bzero(cp->buf, cp->buf_size); 560 | cp->data_len = 0; 561 | } 562 | 563 | static int cmd_parser_init(struct cmd_parser_s *cp, char *buf, uint16_t buf_size) 564 | { 565 | dbg_assert(cp); 566 | cp->buf = buf; 567 | cp->buf_size = buf_size; 568 | cp->data_len = 0; 569 | cp->callback = cmd_completed_cb; 570 | return 0; 571 | } 572 | 573 | static void cmd_parse_byte(struct cmd_parser_s *cp, char value) 574 | { 575 | dbg_assert(cp); 576 | switch (value) { 577 | case '\r': 578 | if (cp->callback != NULL) 579 | cp->callback(cp); 580 | break; 581 | default: 582 | if (cp->data_len < cp->buf_size) 583 | cp->buf[cp->data_len++] = value; 584 | break; 585 | } 586 | } 587 | 588 | static void ticker_cmd_task(struct neurite_data_s *nd) 589 | { 590 | char c; 591 | if (CMD_SERIAL.available() <= 0) 592 | return; 593 | c = CMD_SERIAL.read(); 594 | LOG_SERIAL.printf("%c", c); 595 | cmd_parse_byte(nd->cp, c); 596 | } 597 | 598 | inline void stop_ticker_cmd(struct neurite_data_s *nd) 599 | { 600 | ticker_cmd.detach(); 601 | } 602 | 603 | inline void start_ticker_cmd(struct neurite_data_s *nd) 604 | { 605 | ticker_cmd.detach(); 606 | stop_ticker_cmd(nd); 607 | ticker_cmd.attach_ms(1, ticker_cmd_task, nd); 608 | } 609 | 610 | static void reboot(struct neurite_data_s *nd) 611 | { 612 | log_info("rebooting...\n\r"); 613 | stop_ticker_but(nd); 614 | stop_ticker_mon(nd); 615 | stop_ticker_led(nd); 616 | stop_ticker_cmd(nd); 617 | ESP.restart(); 618 | } 619 | 620 | static void fs_init(struct neurite_data_s *nd) 621 | { 622 | if (!SPIFFS.begin()) { 623 | log_err("failed to mount fs\n\r"); 624 | dbg_assert(0); 625 | } 626 | FSInfo info; 627 | if (!SPIFFS.info(info)) { 628 | log_err("failed to mount fs\n\r"); 629 | dbg_assert(0); 630 | } 631 | log_dbg("Total: %u\n\r", info.totalBytes); 632 | log_dbg("Used: %u\n\r", info.usedBytes); 633 | log_dbg("Block: %u\n\r", info.blockSize); 634 | log_dbg("Page: %u\n\r", info.pageSize); 635 | log_dbg("Max open files: %u\n\r", info.maxOpenFiles); 636 | log_dbg("Max path len: %u\n\r", info.maxPathLength); 637 | 638 | Dir dir = SPIFFS.openDir("/"); 639 | while (dir.next()) { 640 | String fileName = dir.fileName(); 641 | size_t fileSize = dir.fileSize(); 642 | log_dbg("file: %s, size: %s\n\r", 643 | fileName.c_str(), formatBytes(fileSize).c_str()); 644 | fileName = String(); 645 | } 646 | } 647 | 648 | static void cfg_init(struct neurite_data_s *nd) 649 | { 650 | __bzero(&nd->cfg, sizeof(struct neurite_cfg_s)); 651 | sprintf(nd->uid, "neurite-%08x", ESP.getChipId()); 652 | log_dbg("uid: %s\n\r", nd->uid); 653 | sprintf(nd->topic_private, "%s/%s/#", TOPIC_HEADER, nd->uid); 654 | log_dbg("topic_private: %s\n\r", nd->topic_private); 655 | 656 | nd->cfg.get = cfg_get; 657 | nd->cfg.set = cfg_set; 658 | nd->cfg.save = cfg_save; 659 | nd->cfg.load = cfg_load; 660 | nd->cfg.dump = cfg_dump; 661 | 662 | if (!nd->cfg.load(NEURITE_CFG_PATH)) { 663 | log_warn("load cfg failed, try to create\n\r"); 664 | StaticJsonBuffer json_buf; 665 | JsonObject& json = json_buf.createObject(); 666 | if (!json.success()) { 667 | log_fatal("create failed\n\r"); 668 | return; 669 | } 670 | json["ssid"] = SSID1; 671 | json["psk"] = PSK1; 672 | json["topic_to"] = TOPIC_TO_DEFAULT; 673 | json["topic_from"] = TOPIC_FROM_DEFAULT; 674 | json.printTo(nd->cfg.json_buf, NEURITE_CFG_SIZE); 675 | } else { 676 | char tmp[NEURITE_CFG_ITEM_SIZE]; 677 | if (!nd->cfg.get("ssid", tmp, NEURITE_CFG_ITEM_SIZE)) 678 | nd->cfg.set("ssid", SSID1, NEURITE_SSID_LEN); 679 | if (!nd->cfg.get("psk", tmp, NEURITE_CFG_ITEM_SIZE)) 680 | nd->cfg.set("psk", PSK1, NEURITE_PSK_LEN); 681 | if (!nd->cfg.get("topic_to", tmp, NEURITE_CFG_ITEM_SIZE)) 682 | nd->cfg.set("topic_to", TOPIC_TO_DEFAULT, MQTT_TOPIC_LEN); 683 | if (!nd->cfg.get("topic_from", tmp, NEURITE_CFG_ITEM_SIZE)) 684 | nd->cfg.set("topic_from", TOPIC_FROM_DEFAULT, MQTT_TOPIC_LEN); 685 | } 686 | nd->cfg.save(NEURITE_CFG_PATH); 687 | } 688 | 689 | static void handleNotFound(void) 690 | { 691 | log_dbg("in\r\n"); 692 | #ifdef NEURITE_ENABLE_DNSPORTAL 693 | if (!handleFileRead(server->uri().c_str())) { 694 | if (!handleFileRead("/index.html")) 695 | server->send(404, "text/plain", "FileNotFound"); 696 | } 697 | #else 698 | if (!handleFileRead(server->uri().c_str())) { 699 | String message = "File Not Found\n\n"; 700 | message += "URI: "; 701 | message += server->uri(); 702 | message += "\nMethod: "; 703 | message += (server->method() == HTTP_GET)?"GET":"POST"; 704 | message += "\nArguments: "; 705 | message += server->args(); 706 | message += "\n"; 707 | for (int i = 0; i < server->args(); i++) { 708 | message += " " + server->argName(i) + ": " + server->arg(i) + "\n"; 709 | } 710 | server->send(404, "text/plain", message); 711 | message = String(); 712 | } 713 | #endif 714 | log_dbg("out\r\n"); 715 | } 716 | 717 | static String formatBytes(size_t bytes) 718 | { 719 | if (bytes < 1024) { 720 | return String(bytes)+"B"; 721 | } else if (bytes < (1024 * 1024)) { 722 | return String(bytes/1024.0)+"KB"; 723 | } else if (bytes < (1024 * 1024 * 1024)) { 724 | return String(bytes/1024.0/1024.0)+"MB"; 725 | } else { 726 | return String(bytes/1024.0/1024.0/1024.0)+"GB"; 727 | } 728 | } 729 | 730 | static String getContentType(String filename) 731 | { 732 | if (server->hasArg("download")) return "application/octet-stream"; 733 | else if (filename.endsWith(".htm")) return "text/html"; 734 | else if (filename.endsWith(".html")) return "text/html"; 735 | else if (filename.endsWith(".css")) return "text/css"; 736 | else if (filename.endsWith(".json")) return "text/json"; 737 | else if (filename.endsWith(".js")) return "application/javascript"; 738 | else if (filename.endsWith(".png")) return "image/png"; 739 | else if (filename.endsWith(".gif")) return "image/gif"; 740 | else if (filename.endsWith(".jpg")) return "image/jpeg"; 741 | else if (filename.endsWith(".ico")) return "image/x-icon"; 742 | else if (filename.endsWith(".xml")) return "text/xml"; 743 | else if (filename.endsWith(".pdf")) return "application/x-pdf"; 744 | else if (filename.endsWith(".zip")) return "application/x-zip"; 745 | else if (filename.endsWith(".gz")) return "application/x-gzip"; 746 | return "text/plain"; 747 | } 748 | 749 | static bool handleFileRead(const char *p) 750 | { 751 | String path = String(p); 752 | log_dbg("in %s\n\r", path.c_str()); 753 | if (path.endsWith("/")) 754 | path += "index.html"; 755 | String contentType = getContentType(path); 756 | String pathWithGz = path + ".gz"; 757 | if (SPIFFS.exists(pathWithGz) || SPIFFS.exists(path)) { 758 | if (SPIFFS.exists(pathWithGz)) 759 | path += ".gz"; 760 | File file = SPIFFS.open(path, "r"); 761 | log_dbg("streaming size: %u\n\r", file.size()); 762 | size_t sent = server->streamFile(file, contentType); 763 | log_dbg("stream return sent: %u\n\r", sent); 764 | file.close(); 765 | path = String(); 766 | contentType = String(); 767 | pathWithGz = String(); 768 | log_dbg("out\r\n"); 769 | return true; 770 | } 771 | path = String(); 772 | contentType = String(); 773 | pathWithGz = String(); 774 | log_dbg("out not exists\r\n"); 775 | return false; 776 | } 777 | 778 | static void handleFileUpload(void) 779 | { 780 | log_dbg("in\r\n"); 781 | if (server->uri() != "/edit") 782 | return; 783 | HTTPUpload& upload = server->upload(); 784 | if (upload.status == UPLOAD_FILE_START) { 785 | String filename = upload.filename; 786 | if (!filename.startsWith("/")) 787 | filename = "/"+filename; 788 | log_info(""); 789 | LOG_SERIAL.println(filename); 790 | fsUploadFile = SPIFFS.open(filename, "w"); 791 | filename = String(); 792 | } else if (upload.status == UPLOAD_FILE_WRITE) { 793 | //LOG_SERIAL.print("handleFileUpload Data: "); 794 | //LOG_SERIAL.println(upload.currentSize); 795 | if (fsUploadFile) 796 | fsUploadFile.write(upload.buf, upload.currentSize); 797 | } else if (upload.status == UPLOAD_FILE_END) { 798 | if (fsUploadFile) 799 | fsUploadFile.close(); 800 | log_info("done, size: "); 801 | LOG_SERIAL.println(upload.totalSize); 802 | } 803 | log_dbg("out\r\n"); 804 | } 805 | 806 | static void handleFileDelete(void) 807 | { 808 | log_dbg("in\r\n"); 809 | if (server->args() == 0) 810 | return server->send(500, "text/plain", "BAD ARGS"); 811 | String path = server->arg(0); 812 | log_info(""); 813 | LOG_SERIAL.println(path); 814 | if (path == "/") { 815 | log_dbg("out 500\r\n"); 816 | return server->send(500, "text/plain", "BAD PATH"); 817 | } 818 | if (!SPIFFS.exists(path)) { 819 | log_dbg("out 404\r\n"); 820 | return server->send(404, "text/plain", "FileNotFound"); 821 | } 822 | SPIFFS.remove(path); 823 | server->send(200, "text/plain", ""); 824 | path = String(); 825 | log_dbg("out\r\n"); 826 | } 827 | 828 | static void handleFileCreate(void) 829 | { 830 | log_dbg("in\r\n"); 831 | if (server->args() == 0) 832 | return server->send(500, "text/plain", "BAD ARGS"); 833 | String path = server->arg(0); 834 | log_info(""); 835 | LOG_SERIAL.println(path); 836 | if (path == "/") { 837 | log_dbg("out 500 bad path\r\n"); 838 | return server->send(500, "text/plain", "BAD PATH"); 839 | } 840 | if (SPIFFS.exists(path)) { 841 | log_dbg("out 500 file exists\r\n"); 842 | return server->send(500, "text/plain", "FILE EXISTS"); 843 | } 844 | File file = SPIFFS.open(path, "w"); 845 | if (file) { 846 | file.close(); 847 | } else { 848 | log_dbg("out 500 failed\r\n"); 849 | return server->send(500, "text/plain", "CREATE FAILED"); 850 | } 851 | server->send(200, "text/plain", ""); 852 | path = String(); 853 | log_dbg("out\r\n"); 854 | } 855 | 856 | static void handleFileList(void) 857 | { 858 | String path; 859 | log_dbg("in\r\n"); 860 | if (!server->hasArg("dir")) { 861 | path = String("/"); 862 | } else { 863 | path = String(server->arg("dir")); 864 | } 865 | log_dbg(""); 866 | LOG_SERIAL.println(path); 867 | Dir dir = SPIFFS.openDir(path); 868 | 869 | String output = "["; 870 | while (dir.next()) { 871 | File entry = dir.openFile("r"); 872 | if (output != "[") output += ','; 873 | bool isDir = false; 874 | output += "{\"type\":\""; 875 | output += (isDir)?"dir":"file"; 876 | output += "\",\"name\":\""; 877 | output += String(entry.name()).substring(1); 878 | output += "\"}"; 879 | entry.close(); 880 | } 881 | output += "]"; 882 | server->send(200, "text/json", output); 883 | path = String(); 884 | log_dbg("out\r\n"); 885 | } 886 | 887 | static void handleRoot(void) 888 | { 889 | log_dbg("in\r\n"); 890 | if (b_cfg_ready) { 891 | String message = String((const char *)g_nd.uid); 892 | message += " alive "; 893 | message += millis(); 894 | message += " ms"; 895 | server->send(200, "text/plain", message); 896 | message = String(); 897 | } else { 898 | if (!handleFileRead("/index.html")) 899 | server->send(404, "text/plain", "FileNotFound"); 900 | } 901 | log_dbg("out\r\n"); 902 | } 903 | 904 | static void handleSave(void) 905 | { 906 | struct neurite_data_s *nd = &g_nd; 907 | String message; 908 | log_dbg("in\n\r"); 909 | message += "URI: "; 910 | message += server->uri(); 911 | message += "\nMethod: "; 912 | message += (server->method() == HTTP_GET)?"GET":"POST"; 913 | message += "\nArguments: "; 914 | message += server->args(); 915 | message += "\n\n"; 916 | for (int i = 0; iargs(); i++) { 917 | message += server->argName(i) + ": " + server->arg(i) + "\n"; 918 | if (server->argName(i).equals("ssid")) { 919 | if (server->arg(i).length() > NEURITE_SSID_LEN) { 920 | log_warn("ssid too long %d (>%d)\n\r", 921 | server->arg(i).length(), NEURITE_SSID_LEN); 922 | goto err_handle_save; 923 | } else { 924 | nd->cfg.set("ssid", server->arg(i).c_str(), NEURITE_SSID_LEN); 925 | } 926 | } else if (server->argName(i).equals("password")) { 927 | if (server->arg(i).length() > NEURITE_PSK_LEN) { 928 | log_warn("password too long %d (>%d)\n\r", 929 | server->arg(i).length(), NEURITE_PSK_LEN); 930 | goto err_handle_save; 931 | } else { 932 | nd->cfg.set("psk", server->arg(i).c_str(), NEURITE_PSK_LEN); 933 | } 934 | } else { 935 | log_warn("%s not handled\n\r", server->arg(i).c_str()); 936 | } 937 | } 938 | message += "\nGood config, reboot in 3 seconds.\n"; 939 | nd->cfg.save(NEURITE_CFG_PATH); 940 | server->send(200, "text/plain", message); 941 | message = String(); 942 | log_dbg("out ok\n\r"); 943 | ticker_reboot.once_ms(3000, (void (*)(void))reboot); 944 | return; 945 | err_handle_save: 946 | message += "Bad request\n"; 947 | server->send(400, "text/plain", message); 948 | message = String(); 949 | log_dbg("out bad\n\r"); 950 | return; 951 | } 952 | 953 | static void server_config(struct neurite_data_s *nd) 954 | { 955 | server = new ESP8266WebServer(80); 956 | server->on("/list", HTTP_GET, handleFileList); 957 | server->on("/edit", HTTP_PUT, handleFileCreate); 958 | server->on("/edit", HTTP_DELETE, handleFileDelete); 959 | server->on("/edit", HTTP_POST, []() { 960 | server->send(200, "text/plain", ""); 961 | }, handleFileUpload); 962 | server->on("/save", HTTP_POST, handleSave); 963 | server->onNotFound(handleNotFound); 964 | 965 | server->on("/all", HTTP_GET, []() { 966 | String json = "{"; 967 | json += "\"heap\":"+String(ESP.getFreeHeap()); 968 | json += ", \"analog\":"+String(analogRead(A0)); 969 | json += ", \"gpio\":"+String((uint32_t)(((GPI | GPO) & 0xFFFF) | ((GP16I & 0x01) << 16))); 970 | json += "}"; 971 | server->send(200, "text/json", json); 972 | json = String(); 973 | }); 974 | server->on("/wifiscan", HTTP_GET, []() { 975 | static bool scanning = false; 976 | if (scanning) { 977 | server->send(202, "text/plain", ""); 978 | log_dbg("busy scanning, return\r\n"); 979 | return; 980 | } 981 | scanning = true; 982 | log_dbg("scan start\r\n"); 983 | int n = WiFi.scanNetworks(); 984 | log_dbg("scan done\r\n"); 985 | if (n > 0) { 986 | #if 0 987 | String json = "{"; 988 | for (int i = 0; i < n; i++) { 989 | if (i > 0) 990 | json += ", "; 991 | json += "\"" + WiFi.SSID(i) + "\":" + String(WiFi.RSSI(i)); 992 | } 993 | json += "}"; 994 | #else 995 | String json = "["; 996 | for (int i = 0; i < n; i++) { 997 | if (i > 0) 998 | json += ","; 999 | json += "{\"ssid\":\"" + WiFi.SSID(i) + "\",\"rssi\":" + String(WiFi.RSSI(i)) + "}"; 1000 | } 1001 | json += "]"; 1002 | #endif 1003 | server->send(200, "text/json", json); 1004 | log_dbg(""); 1005 | LOG_SERIAL.println(json); 1006 | json = String(); 1007 | } else { 1008 | server->send(204, "text/plain", "No WLAN found"); 1009 | log_dbg("No WLAN found\r\n"); 1010 | } 1011 | scanning = false; 1012 | }); 1013 | server->on("/ip", HTTP_GET, []() { 1014 | String ipstr = String(); 1015 | if((WiFi.getMode() & WIFI_STA)) 1016 | ipstr = WiFi.localIP().toString(); 1017 | else 1018 | ipstr = WiFi.softAPIP().toString(); 1019 | server->send(200, "text/plain", ipstr); 1020 | log_dbg(""); 1021 | LOG_SERIAL.println(ipstr); 1022 | ipstr = String(); 1023 | }); 1024 | 1025 | server->on("/", handleRoot); 1026 | } 1027 | 1028 | enum { 1029 | CFG_ST_0 = 0, 1030 | CFG_ST_1, 1031 | CFG_ST_2 1032 | }; 1033 | static int cfg_st = CFG_ST_0; 1034 | 1035 | static inline void update_cfg_state(int st) 1036 | { 1037 | log_dbg("-> CFG_ST_%d\n\r", st); 1038 | cfg_st = st; 1039 | } 1040 | 1041 | #ifdef NEURITE_ENABLE_MDNS 1042 | const char *host = "neurite"; 1043 | #endif 1044 | #ifdef NEURITE_ENABLE_DNSPORTAL 1045 | DNSServer dnsServer; 1046 | #endif 1047 | IPAddress apIP(192, 168, 4, 1); 1048 | inline void neurite_cfg_worker(void) 1049 | { 1050 | struct neurite_data_s *nd = &g_nd; 1051 | switch (cfg_st) { 1052 | case CFG_ST_0: 1053 | analogWrite(NEURITE_LED, 300); 1054 | WiFi.mode(WIFI_AP); 1055 | WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0)); 1056 | WiFi.softAP(nd->uid); 1057 | LOG_SERIAL.print("AP IP address: "); 1058 | LOG_SERIAL.println(apIP); 1059 | update_cfg_state(CFG_ST_1); 1060 | break; 1061 | case CFG_ST_1: 1062 | #ifdef NEURITE_ENABLE_MDNS 1063 | MDNS.begin(host); 1064 | LOG_SERIAL.print("Open http://"); 1065 | LOG_SERIAL.print(host); 1066 | LOG_SERIAL.println(".local to get started"); 1067 | #endif 1068 | #ifdef NEURITE_ENABLE_DNSPORTAL 1069 | dnsServer.start(53, "linkgo.io", apIP); 1070 | log_dbg("DNS server started\n\r"); 1071 | #endif 1072 | server_config(nd); 1073 | server->begin(); 1074 | log_dbg("HTTP server started\n\r"); 1075 | log_dbg("heap free: %d\n\r", ESP.getFreeHeap()); 1076 | update_cfg_state(CFG_ST_2); 1077 | break; 1078 | case CFG_ST_2: 1079 | #ifdef NEURITE_ENABLE_DNSPORTAL 1080 | dnsServer.processNextRequest(); 1081 | #endif 1082 | server->handleClient(); 1083 | break; 1084 | default: 1085 | log_err("unknown cfg state: %d\n\r", cfg_st); 1086 | break; 1087 | } 1088 | } 1089 | 1090 | inline void neurite_worker(void) 1091 | { 1092 | struct neurite_data_s *nd = &g_nd; 1093 | switch (worker_st) { 1094 | case WORKER_ST_0: 1095 | stop_ticker_mon(nd); 1096 | start_ticker_led_blink(nd); 1097 | wifi_connect(nd); 1098 | update_worker_state(WORKER_ST_1); 1099 | break; 1100 | case WORKER_ST_1: 1101 | if (!wifi_check_status(nd)) 1102 | break; 1103 | nd->wifi_connected = true; 1104 | log_dbg("WiFi connected\n\r"); 1105 | log_info("STA IP address: "); 1106 | LOG_SERIAL.println(WiFi.localIP()); 1107 | update_worker_state(WORKER_ST_2); 1108 | break; 1109 | case WORKER_ST_2: 1110 | if (digitalRead(NEURITE_BUTTON) == LOW) 1111 | ota_over_http(OTA_URL_DEFAULT); 1112 | mqtt_config(nd); 1113 | update_worker_state(WORKER_ST_3); 1114 | break; 1115 | case WORKER_ST_3: 1116 | if (!mqtt_check_status(nd)) { 1117 | if (!wifi_check_status(nd)) 1118 | update_worker_state(WORKER_ST_0); 1119 | else 1120 | mqtt_connect(nd); 1121 | break; 1122 | } 1123 | nd->mqtt_connected = true; 1124 | 1125 | char topic_from[MQTT_TOPIC_LEN]; 1126 | nd->cfg.get("topic_from", topic_from, MQTT_TOPIC_LEN); 1127 | char topic_to[MQTT_TOPIC_LEN]; 1128 | nd->cfg.get("topic_to", topic_to, MQTT_TOPIC_LEN); 1129 | 1130 | mqtt_cli.subscribe(topic_from); 1131 | log_info("subscribe: %s\n\r", topic_from); 1132 | mqtt_cli.subscribe(nd->topic_private); 1133 | log_info("subscribe: %s\n\r", nd->topic_private); 1134 | char payload_buf[32]; 1135 | dbg_assert(payload_buf); 1136 | sprintf(payload_buf, "checkin: %s", nd->uid); 1137 | mqtt_cli.publish(topic_to, (const char *)payload_buf); 1138 | __bzero(payload_buf, sizeof(payload_buf)); 1139 | sprintf(payload_buf, "ip: %s", WiFi.localIP().toString().c_str()); 1140 | mqtt_cli.publish(topic_to, (const char *)payload_buf); 1141 | 1142 | start_ticker_led_breath(nd); 1143 | start_ticker_mon(nd); 1144 | CMD_SERIAL.println(FPSTR(STR_READY)); 1145 | log_dbg("heap free: %d\n\r", ESP.getFreeHeap()); 1146 | #ifdef NEURITE_ENABLE_SERVER 1147 | server_config(nd); 1148 | server->begin(); 1149 | log_dbg("HTTP server started\n\r"); 1150 | log_dbg("heap free: %d\n\r", ESP.getFreeHeap()); 1151 | #endif 1152 | update_worker_state(WORKER_ST_4); 1153 | break; 1154 | case WORKER_ST_4: 1155 | mqtt_cli.loop(); 1156 | #ifdef NEURITE_ENABLE_SERVER 1157 | server->handleClient(); 1158 | #endif 1159 | break; 1160 | default: 1161 | log_err("unknown worker state: %d\n\r", worker_st); 1162 | break; 1163 | } 1164 | } 1165 | 1166 | void neurite_init(void) 1167 | { 1168 | struct neurite_data_s *nd = &g_nd; 1169 | log_dbg("in\n\r"); 1170 | 1171 | __bzero(cfg_buf, NEURITE_CFG_SIZE); 1172 | __bzero(nd, sizeof(struct neurite_data_s)); 1173 | __bzero(&g_cp, sizeof(struct cmd_parser_s)); 1174 | nd->cp = &g_cp; 1175 | __bzero(cmd_buf, NEURITE_CMD_BUF_SIZE); 1176 | cmd_parser_init(nd->cp, cmd_buf, NEURITE_CMD_BUF_SIZE); 1177 | 1178 | fs_init(nd); 1179 | cfg_init(nd); 1180 | 1181 | if (cfg_validate(nd)) { 1182 | b_cfg_ready = true; 1183 | log_dbg("cfg ready\n\r"); 1184 | } else { 1185 | b_cfg_ready = false; 1186 | log_dbg("cfg not ready\n\r"); 1187 | } 1188 | 1189 | start_ticker_but(nd); 1190 | start_ticker_cmd(nd); 1191 | log_dbg("out\n\r"); 1192 | } 1193 | 1194 | void setup() 1195 | { 1196 | Serial.begin(115200); 1197 | Serial.setDebugOutput(false); 1198 | Serial.printf("\n\r"); 1199 | Serial.flush(); 1200 | Serial1.begin(115200); 1201 | Serial1.setDebugOutput(false); 1202 | Serial1.printf("\n\r"); 1203 | Serial1.flush(); 1204 | pinMode(NEURITE_LED, OUTPUT); 1205 | digitalWrite(NEURITE_LED, HIGH); 1206 | pinMode(NEURITE_BUTTON, INPUT); 1207 | log_dbg("heap free: %d\n\r", ESP.getFreeHeap()); 1208 | log_dbg("flash size: %d\n\r", ESP.getFlashChipRealSize()); 1209 | log_dbg("sketch size: %d\n\r", ESP.getSketchSize()); 1210 | log_dbg("sketch free: %d\n\r", ESP.getFreeSketchSpace()); 1211 | 1212 | neurite_init(); 1213 | } 1214 | 1215 | void loop() 1216 | { 1217 | if (b_cfg_ready) 1218 | neurite_worker(); 1219 | else 1220 | neurite_cfg_worker(); 1221 | #ifdef NEURITE_ENABLE_USER 1222 | if (worker_st == WORKER_ST_4) 1223 | neurite_user_loop(); 1224 | #endif 1225 | } 1226 | -------------------------------------------------------------------------------- /src/neurite_priv.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2016 Linkgo LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #ifndef __NEURITE_PRIV_H__ 26 | #define __NEURITE_PRIV_H__ 27 | 28 | #define NEURITE_CFG_PATH "/config.json" 29 | #define NEURITE_CFG_SIZE 1024 30 | #define NEURITE_CFG_ITEM_SIZE 64 31 | #define NEURITE_CMD_BUF_SIZE 256 32 | #define NEURITE_UID_LEN 32 33 | #define NEURITE_SSID_LEN 64 34 | #define NEURITE_PSK_LEN 64 35 | 36 | #define NEURITE_CFG_ITEM_LEN 64 37 | 38 | #define MQTT_TOPIC_LEN 64 39 | #define MQTT_MSG_LEN 256 40 | 41 | #define NEURITE_LED 5 42 | #define NEURITE_BUTTON 0 43 | 44 | struct cmd_parser_s; 45 | typedef void (*cmd_parser_cb_fp)(struct cmd_parser_s *cp); 46 | 47 | struct cmd_parser_s { 48 | char *buf; 49 | uint16_t buf_size; 50 | uint16_t data_len; 51 | bool cmd_begin; 52 | cmd_parser_cb_fp callback; 53 | }; 54 | 55 | struct neurite_cfg_s { 56 | char json_buf[NEURITE_CFG_SIZE]; 57 | bool (*get)(const char *str, char *buf, size_t size); 58 | bool (*set)(const char *str, const char *buf, size_t size); 59 | bool (*save)(const char *file); 60 | bool (*load)(const char *file); 61 | bool (*dump)(void); 62 | }; 63 | 64 | typedef char *(*p_get_cfg)(char *str); 65 | 66 | struct neurite_data_s { 67 | bool wifi_connected; 68 | bool mqtt_connected; 69 | struct neurite_cfg_s cfg; 70 | struct cmd_parser_s *cp; 71 | char uid[NEURITE_UID_LEN]; 72 | char topic_private[MQTT_TOPIC_LEN]; 73 | }; 74 | 75 | struct neurite_data_s g_nd; 76 | WiFiClient wifi_cli; 77 | PubSubClient mqtt_cli(wifi_cli); 78 | 79 | #endif /* __NEURITE_PRIV_H__ */ 80 | -------------------------------------------------------------------------------- /src/neurite_user.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2016 Linkgo LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #include 26 | 27 | #include "neurite_utils.h" 28 | 29 | #include 30 | #ifdef NEURITE_ENABLE_WIFIMULTI 31 | #include 32 | #endif 33 | #include 34 | #include 35 | #include 36 | #ifdef NEURITE_ENABLE_MDNS 37 | #include 38 | #endif 39 | #ifdef NEURITE_ENABLE_DNSPORTAL 40 | #include 41 | #endif 42 | #include 43 | #include 44 | #include 45 | #include "FS.h" 46 | 47 | extern "C" { 48 | #include "osapi.h" 49 | #include "ets_sys.h" 50 | #include "user_interface.h" 51 | } 52 | 53 | #include "neurite_priv.h" 54 | 55 | extern struct neurite_data_s g_nd; 56 | 57 | #ifdef NEURITE_ENABLE_USER 58 | /* 59 | * User Advanced Development 60 | * 61 | * Brief: 62 | * Below interfaces are objected to advanced development based on Neurite. 63 | * Also these code can be take as a reference. Thus they are extended 64 | * features, which are not mandatory in Neurite core service. 65 | * 66 | * Benefits: 67 | * Thanks to Neurite, it's more easily to use below features: 68 | * 1. OTA 69 | * 2. MQTT 70 | * 3. Peripherals 71 | */ 72 | 73 | #define USER_LOOP_INTERVAL 1000 74 | 75 | static bool b_user_loop_run = true; 76 | 77 | enum { 78 | USER_ST_0 = 0, 79 | USER_ST_1, 80 | }; 81 | static int user_st = USER_ST_0; 82 | 83 | static inline void update_user_state(int st) 84 | { 85 | log_dbg("-> USER_ST_%d\n\r", st); 86 | user_st = st; 87 | } 88 | 89 | void neurite_user_worker(void) 90 | { 91 | /* add user stuff here */ 92 | } 93 | 94 | void neurite_user_loop(void) 95 | { 96 | static uint32_t prev_time = 0; 97 | if (b_user_loop_run == false) 98 | return; 99 | if ((millis() - prev_time) < USER_LOOP_INTERVAL) 100 | return; 101 | prev_time = millis(); 102 | switch (user_st) { 103 | case USER_ST_0: 104 | neurite_user_setup(); 105 | update_user_state(USER_ST_1); 106 | break; 107 | case USER_ST_1: 108 | neurite_user_worker(); 109 | break; 110 | default: 111 | log_err("unknown user state: %d\n\r", user_st); 112 | break; 113 | } 114 | } 115 | 116 | /* called on critical neurite behavior such as OTA */ 117 | void neurite_user_hold(void) 118 | { 119 | log_dbg("\n\r"); 120 | update_user_state(USER_ST_0); 121 | } 122 | 123 | /* will be called after neurite system setup */ 124 | void neurite_user_setup(void) 125 | { 126 | log_dbg("\n\r"); 127 | } 128 | 129 | /* called once on mqtt message received */ 130 | void neurite_user_mqtt(char *topic, byte *payload, unsigned int length) 131 | { 132 | struct neurite_data_s *nd = &g_nd; 133 | if (strncmp(topic, nd->topic_private, strlen(nd->topic_private) - 2) == 0) { 134 | char *subtopic = topic + strlen(nd->topic_private) - 2; 135 | char *token = NULL; 136 | token = strtok(subtopic, "/"); 137 | if (strcmp(token, "io") == 0) { 138 | log_dbg("hit io, payload: %c\n\r", payload[0]); 139 | } 140 | } 141 | char topic_from[MQTT_TOPIC_LEN] = {0}; 142 | nd->cfg.get("topic_from", topic_from, MQTT_TOPIC_LEN); 143 | if (strcmp(topic, topic_from) == 0) { 144 | } 145 | } 146 | 147 | /* time_ms: the time delta in ms of button press/release cycle. */ 148 | void neurite_user_button(int time_ms) 149 | { 150 | struct neurite_data_s *nd = &g_nd; 151 | if (time_ms >= 50) { 152 | /* do something on button event */ 153 | if (nd->mqtt_connected) { 154 | static int val = 0; 155 | char buf[4]; 156 | val = 1 - val; 157 | 158 | char topic_to[MQTT_TOPIC_LEN] = {0}; 159 | nd->cfg.get("topic_to", topic_to, MQTT_TOPIC_LEN); 160 | 161 | if (val) 162 | mqtt_cli.publish(topic_to, "light on"); 163 | else 164 | mqtt_cli.publish(topic_to, "light off"); 165 | } 166 | } 167 | } 168 | #endif 169 | -------------------------------------------------------------------------------- /src/neurite_utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2016 Linkgo LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #ifndef __NEURITE_UTILS_H__ 26 | #define __NEURITE_UTILS_H__ 27 | 28 | /* 29 | * Configs 30 | */ 31 | 32 | #define OTA_URL_DEFAULT "http://neurite-ota.oss-cn-shanghai.aliyuncs.com/firmware.bin" 33 | #define TOPIC_HEADER "/neuro" 34 | #define TOPIC_TO_DEFAULT "/neuro/chatroom" 35 | #define TOPIC_FROM_DEFAULT "/neuro/chatroom" 36 | #define SSID1 "ssid1" 37 | #define PSK1 "psk1" 38 | #define SSID2 "ssid2" 39 | #define PSK2 "psk2" 40 | #define MQTT_SERVER "linkgo.io" 41 | 42 | /* 43 | * Features 44 | */ 45 | //#define NEURITE_ENABLE_WIFIMULTI 46 | #define NEURITE_ENABLE_SERVER /* typical for dev only */ 47 | //#define NEURITE_ENABLE_MDNS 48 | #define NEURITE_ENABLE_DNSPORTAL 49 | #define NEURITE_ENABLE_USER 50 | //#define NEURITE_BUILD_DEV 51 | 52 | /* 53 | * Log 54 | */ 55 | #define LOG_ALL 0 56 | #define LOG_DEBUG 1 57 | #define LOG_INFO 2 58 | #define LOG_WARN 3 59 | #define LOG_ERROR 4 60 | #define LOG_FATAL 5 61 | #define LOG_LEVEL LOG_ALL 62 | 63 | #define CMD_SERIAL Serial 64 | #ifdef NEURITE_BUILD_DEV 65 | #define LOG_SERIAL Serial 66 | #else 67 | #define LOG_SERIAL Serial1 68 | #endif 69 | 70 | #define __dec (millis()/1000) 71 | #define __frac (millis()%1000) 72 | #define APP_PRINTF LOG_SERIAL.printf 73 | 74 | #define log_dbg(msg, args...) \ 75 | do { \ 76 | if (LOG_LEVEL <= LOG_DEBUG) { \ 77 | APP_PRINTF("[%6lu.%03lu] D/%s: " msg, __dec, __frac, __func__, ##args); \ 78 | } \ 79 | } while (0) 80 | #define log_info(msg, args...) \ 81 | do { \ 82 | if (LOG_LEVEL <= LOG_INFO) { \ 83 | APP_PRINTF("[%6lu.%03lu] I/%s: " msg, __dec, __frac, __func__, ##args); \ 84 | } \ 85 | } while (0) 86 | #define log_warn(msg, args...) \ 87 | do { \ 88 | if (LOG_LEVEL <= LOG_WARN) { \ 89 | APP_PRINTF("[%6lu.%03lu] W/%s: " msg, __dec, __frac, __func__, ##args); \ 90 | } \ 91 | } while (0) 92 | #define log_err(msg, args...) \ 93 | do { \ 94 | if (LOG_LEVEL <= LOG_ERROR) { \ 95 | APP_PRINTF("[%6lu.%03lu] E/%s: " msg, __dec, __frac, __func__, ##args); \ 96 | } \ 97 | } while (0) 98 | #define log_fatal(msg, args...) \ 99 | do { \ 100 | if (LOG_LEVEL <= LOG_FATAL) { \ 101 | APP_PRINTF("[%6lu.%03lu] F/%s: " msg, __dec, __frac, __func__, ##args); \ 102 | } \ 103 | } while (0) 104 | 105 | /* 106 | * Assertion 107 | */ 108 | #define ASSERT_NONE 0 109 | #define ASSERT_ALL 1 110 | #define ASSERT_LEVEL ASSERT_ALL 111 | 112 | #if (ASSERT_LEVEL >= ASSERT_ALL) 113 | #define _OS_ASSERT(exp) \ 114 | do { \ 115 | if (exp) { \ 116 | } else { \ 117 | log_fatal("assert failed: " #exp " at %s %d!\n", __FILE__, __LINE__); \ 118 | while (1) \ 119 | yield(); \ 120 | } \ 121 | } while (0) 122 | #else 123 | #define _OS_ASSERT(exp) (void)((0)) 124 | #endif 125 | 126 | #define dbg_assert(exp) _OS_ASSERT(exp) 127 | 128 | /* 129 | * Other Utils 130 | */ 131 | 132 | #define __bzero(m,s) memset(m,0,s) 133 | 134 | #endif /* __NEURITE_UTILS_H__ */ 135 | --------------------------------------------------------------------------------