├── .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 [](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 | 
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 |
--------------------------------------------------------------------------------