├── .gitignore ├── .travis.yml ├── Eagle ├── Domophone.rar ├── eagle.epf ├── rcl.lbr ├── unt.lbr ├── untitled.boardoutline.ger ├── untitled.boardoutline.gpi ├── untitled.bottomlayer.ger ├── untitled.bottomlayer.gpi ├── untitled.bottomsilkscreen.ger ├── untitled.bottomsilkscreen.gpi ├── untitled.bottomsoldermask.ger ├── untitled.bottomsoldermask.gpi ├── untitled.brd ├── untitled.drills.dri ├── untitled.drills.xln ├── untitled.sch ├── untitled.toplayer.ger ├── untitled.toplayer.gpi ├── untitled.topsilkscreen.ger ├── untitled.topsilkscreen.gpi ├── untitled.topsoldermask.ger └── untitled.topsoldermask.gpi ├── Notes ├── 8XRE86N0JH517J9HHI-226x300.png ├── NodeMcu-pinout-600x531.jpg └── Note.txt ├── README.md ├── lib ├── pubsubclient-master │ ├── .gitignore │ ├── CHANGES.txt │ ├── Doxyfile │ ├── LICENSE.txt │ ├── README.mediawiki │ ├── examples │ │ ├── ESP8266-OTA │ │ │ └── ESP8266-OTA.ino │ │ ├── mqtt_auth │ │ │ └── mqtt_auth.ino │ │ ├── mqtt_basic │ │ │ └── mqtt_basic.ino │ │ ├── mqtt_publish_in_callback │ │ │ └── mqtt_publish_in_callback.ino │ │ ├── mqtt_publish_large │ │ │ └── mqtt_publish_large.ino │ │ ├── mqtt_qos │ │ │ └── mqtt_qos.ino │ │ ├── mqtt_stream │ │ │ └── mqtt_stream.ino │ │ ├── mqtt_subscriber │ │ │ └── mqtt_subscriber.ino │ │ └── mqtt_will │ │ │ └── mqtt_will.ino │ ├── keywords.txt │ ├── library.properties │ ├── src │ │ ├── MQTT.cpp │ │ ├── MQTT.h │ │ ├── PubSubClient.cpp │ │ ├── PubSubClient.h │ │ └── PubSubClient_JSON.h │ └── tests │ │ ├── .gitignore │ │ ├── Makefile │ │ ├── README.md │ │ ├── src │ │ ├── connect_spec.cpp │ │ ├── keepalive_spec.cpp │ │ ├── lib │ │ │ ├── Arduino.h │ │ │ ├── BDDTest.cpp │ │ │ ├── BDDTest.h │ │ │ ├── Buffer.cpp │ │ │ ├── Buffer.h │ │ │ ├── Client.h │ │ │ ├── IPAddress.h │ │ │ ├── ShimClient.cpp │ │ │ ├── ShimClient.h │ │ │ ├── Stream.cpp │ │ │ ├── Stream.h │ │ │ └── trace.h │ │ ├── publish_spec.cpp │ │ ├── receive_spec.cpp │ │ └── subscribe_spec.cpp │ │ ├── testcases │ │ ├── __init__.py │ │ ├── mqtt_basic.py │ │ ├── mqtt_publish_in_callback.py │ │ └── settings.py │ │ └── testsuite.py └── readme.txt ├── platformio.ini └── src ├── boot.ino ├── config ├── debug.h ├── events.h ├── general.h ├── hardware.h ├── include.h ├── mqtt.h └── wifi.h ├── events.ino ├── led.ino ├── main.ino ├── mqtt.ino ├── relay.ino └── wifi.ino /.gitignore: -------------------------------------------------------------------------------- 1 | Eagle/*.l#* 2 | Eagle/*.b#* 3 | Eagle/*.s#* 4 | .pioenvs 5 | .piolibdeps 6 | .clang_complete 7 | .gcc-flags.json 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # Continuous Integration (CI) is the practice, in software 2 | # engineering, of merging all developer working copies with a shared mainline 3 | # several times a day < http://docs.platformio.org/page/ci/index.html > 4 | # 5 | # Documentation: 6 | # 7 | # * Travis CI Embedded Builds with PlatformIO 8 | # < https://docs.travis-ci.com/user/integration/platformio/ > 9 | # 10 | # * PlatformIO integration with Travis CI 11 | # < http://docs.platformio.org/page/ci/travis.html > 12 | # 13 | # * User Guide for `platformio ci` command 14 | # < http://docs.platformio.org/page/userguide/cmd_ci.html > 15 | # 16 | # 17 | # Please choice one of the following templates (proposed below) and uncomment 18 | # it (remove "# " before each line) or use own configuration according to the 19 | # Travis CI documentation (see above). 20 | # 21 | 22 | 23 | # 24 | # Template #1: General project. Test it using existing `platformio.ini`. 25 | # 26 | 27 | # language: python 28 | # python: 29 | # - "2.7" 30 | # 31 | # sudo: false 32 | # cache: 33 | # directories: 34 | # - "~/.platformio" 35 | # 36 | # install: 37 | # - pip install -U platformio 38 | # 39 | # script: 40 | # - platformio run 41 | 42 | 43 | # 44 | # Template #2: The project is intended to by used as a library with examples 45 | # 46 | 47 | # language: python 48 | # python: 49 | # - "2.7" 50 | # 51 | # sudo: false 52 | # cache: 53 | # directories: 54 | # - "~/.platformio" 55 | # 56 | # env: 57 | # - PLATFORMIO_CI_SRC=path/to/test/file.c 58 | # - PLATFORMIO_CI_SRC=examples/file.ino 59 | # - PLATFORMIO_CI_SRC=path/to/test/directory 60 | # 61 | # install: 62 | # - pip install -U platformio 63 | # 64 | # script: 65 | # - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N 66 | -------------------------------------------------------------------------------- /Eagle/Domophone.rar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xDWart/Domophone/725107507ecad677b6d9c493ca5921e75af19886/Eagle/Domophone.rar -------------------------------------------------------------------------------- /Eagle/eagle.epf: -------------------------------------------------------------------------------- 1 | [Eagle] 2 | Version="07 07 00" 3 | Platform="Windows" 4 | Serial="62191E841E-LSR-WLM-1EL" 5 | Globals="Globals" 6 | Desktop="Desktop" 7 | 8 | [Globals] 9 | AutoSaveProject=1 10 | UsedLibrary="unt.lbr" 11 | UsedLibrary="rcl.lbr" 12 | 13 | [Win_1] 14 | Type="Board Editor" 15 | Loc="0 0 1279 767" 16 | State=3 17 | Number=2 18 | File="untitled.brd" 19 | View="-24.537 -0.785112 47.6864 56.9931" 20 | WireWidths=" 0 0.3048 0.8128 1.016 1.27 1.4224 1.6764 1.778 1.9304 2.1844 2.54 3.81 6.4516 0.254 0.6096 0.4064" 21 | PadDiameters=" 0.254 0.3048 0.4064 0.6096 0.8128 1.016 1.27 1.4224 1.6764 1.778 1.9304 2.1844 2.54 3.81 6.4516 0" 22 | PadDrills=" 0.5 0.6 0.7 0.9 1 1.1 1.2 1.3 1.4 1.5 1.6 2 2.2 2.8 3.2 0.8" 23 | ViaDiameters=" 0.254 0.3048 0.4064 0.6096 0.8128 1.016 1.27 1.4224 1.6764 1.778 1.9304 2.1844 2.54 3.81 6.4516 0" 24 | ViaDrills=" 0.7 0.8 0.9 1 1.1 1.2 1.3 1.4 1.5 1.6 2 2.2 2.8 3.2 0.6 0.3302" 25 | HoleDrills=" 0.8 0.9 1.1 1.2 1.3 1.4 1.6 2 2.2 2.8 3.2 0.6 2.54 1 1.5 1.524" 26 | TextSizes=" 0.254 0.4064 0.6096 0.8128 1.016 1.4224 1.6764 1.9304 2.1844 2.54 3.81 5.08 6.4516 1.778 0.3048 1.27" 27 | PolygonSpacings=" 0.254 0.3048 0.4064 0.6096 0.8128 1.016 1.4224 1.6764 1.778 1.9304 2.1844 2.54 3.81 5.08 6.4516 1.27" 28 | PolygonIsolates=" 0.254 0.3048 0.4064 0.6096 0.8128 1.016 1.27 1.4224 1.6764 1.778 1.9304 2.1844 2.54 3.81 6.4516 0" 29 | MiterRadiuss=" 0.254 0.3175 0.635 1.27 2.54 1 2 2.5 5 7.5 10 0" 30 | DimensionWidths=" 0 0.127 0.254 0.1 0.26 0.13" 31 | DimensionExtWidths=" 0.127 0.254 0.1 0.13 0.26 0" 32 | DimensionExtLengths=" 1.27 2.54 1 2 3 0" 33 | DimensionExtOffsets=" 1.27 2.54 1 2 3 0" 34 | SmdSizes=" 0.3048 0.1524 0.4064 0.2032 0.6096 0.3048 0.8128 0.4064 1.016 0.508 1.27 0.6604 1.4224 0.7112 1.6764 0.8128 1.778 0.9144 1.9304 0.9652 2.1844 1.0668 2.54 1.27 3.81 1.9304 5.08 2.54 6.4516 3.2512 1.27 0.635" 35 | WireBend=4 36 | WireBendSet=0 37 | WireCap=1 38 | MiterStyle=0 39 | PadShape=0 40 | ViaShape=1 41 | PolygonPour=0 42 | PolygonRank=1 43 | PolygonThermals=1 44 | PolygonOrphans=0 45 | TextRatio=8 46 | DimensionUnit=1 47 | DimensionPrecision=2 48 | DimensionShowUnit=0 49 | PinDirection=3 50 | PinFunction=0 51 | PinLength=2 52 | PinVisible=3 53 | SwapLevel=0 54 | ArcDirection=0 55 | AddLevel=2 56 | PadsSameType=0 57 | Layer=1 58 | 59 | [Win_2] 60 | Type="Schematic Editor" 61 | Loc="0 0 1279 767" 62 | State=1 63 | Number=1 64 | File="untitled.sch" 65 | View="-47.2344 10.9587 174.663 153.604" 66 | WireWidths=" 0 0.3048 0.6096 0.8128 1.016 1.27 1.4224 1.6764 1.778 1.9304 2.1844 2.54 3.81 6.4516 0.4064 0.1524" 67 | PadDiameters=" 0.254 0.3048 0.4064 0.6096 0.8128 1.016 1.27 1.4224 1.6764 1.778 1.9304 2.1844 2.54 3.81 6.4516 0" 68 | PadDrills=" 0.5 0.6 0.7 0.9 1 1.1 1.2 1.3 1.4 1.5 1.6 2 2.2 2.8 3.2 0.8" 69 | ViaDiameters=" 0.254 0.3048 0.4064 0.6096 0.8128 1.016 1.27 1.4224 1.6764 1.778 1.9304 2.1844 2.54 3.81 6.4516 0" 70 | ViaDrills=" 0.5 0.7 0.8 0.9 1 1.1 1.2 1.3 1.4 1.5 1.6 2 2.2 2.8 3.2 0.6" 71 | HoleDrills=" 0.5 0.7 0.8 0.9 1 1.1 1.2 1.3 1.4 1.5 1.6 2 2.2 2.8 3.2 0.6" 72 | TextSizes=" 0.254 0.3048 0.4064 0.6096 0.8128 1.016 1.27 1.4224 1.6764 1.9304 2.1844 2.54 3.81 5.08 6.4516 1.778" 73 | PolygonSpacings=" 0.254 0.3048 0.4064 0.6096 0.8128 1.016 1.4224 1.6764 1.778 1.9304 2.1844 2.54 3.81 5.08 6.4516 1.27" 74 | PolygonIsolates=" 0.254 0.3048 0.4064 0.6096 0.8128 1.016 1.27 1.4224 1.6764 1.778 1.9304 2.1844 2.54 3.81 6.4516 0" 75 | MiterRadiuss=" 0.254 0.3175 0.635 1.27 2.54 1 2 2.5 5 7.5 10 0" 76 | DimensionWidths=" 0 0.127 0.254 0.1 0.26 0.13" 77 | DimensionExtWidths=" 0.127 0.254 0.1 0.13 0.26 0" 78 | DimensionExtLengths=" 1.27 2.54 1 2 3 0" 79 | DimensionExtOffsets=" 1.27 2.54 1 2 3 0" 80 | SmdSizes=" 0.3048 0.1524 0.4064 0.2032 0.6096 0.3048 0.8128 0.4064 1.016 0.508 1.27 0.6604 1.4224 0.7112 1.6764 0.8128 1.778 0.9144 1.9304 0.9652 2.1844 1.0668 2.54 1.27 3.81 1.9304 5.08 2.54 6.4516 3.2512 1.27 0.635" 81 | WireBend=0 82 | WireBendSet=31 83 | WireCap=1 84 | MiterStyle=0 85 | PadShape=0 86 | ViaShape=0 87 | PolygonPour=0 88 | PolygonRank=0 89 | PolygonThermals=1 90 | PolygonOrphans=0 91 | TextRatio=8 92 | DimensionUnit=1 93 | DimensionPrecision=2 94 | DimensionShowUnit=0 95 | PinDirection=3 96 | PinFunction=0 97 | PinLength=2 98 | PinVisible=3 99 | SwapLevel=0 100 | ArcDirection=0 101 | AddLevel=2 102 | PadsSameType=0 103 | Layer=91 104 | Views=" 1: -47.2344 10.9587 174.663 153.604" 105 | Sheet="1" 106 | 107 | [Win_3] 108 | Type="Control Panel" 109 | Loc="304 298 903 697" 110 | State=2 111 | Number=0 112 | 113 | [Desktop] 114 | Screen="2560 1024" 115 | Window="Win_1" 116 | Window="Win_2" 117 | Window="Win_3" 118 | -------------------------------------------------------------------------------- /Eagle/untitled.boardoutline.gpi: -------------------------------------------------------------------------------- 1 | Generated by EAGLE CAM Processor 8.2.0 2 | 3 | Photoplotter Info File: d:/git/Domophone/Eagle_v2/untitled.boardoutline.gpi 4 | 5 | Date : 14.05.2017 22:12 6 | Plotfile : d:/git/Domophone/Eagle_v2/untitled.boardoutline.ger 7 | Apertures : generated: 8 | Device : Gerber RS-274-X photoplotter, coordinate format 2.5 inch 9 | 10 | Parameter settings: 11 | 12 | Emulate Apertures : no 13 | Tolerance Draw + : 0.00 % 14 | Tolerance Draw - : 0.00 % 15 | Tolerance Flash + : 0.00 % 16 | Tolerance Flash - : 0.00 % 17 | Rotate : no 18 | Mirror : no 19 | Optimize : yes 20 | Auto fit : yes 21 | OffsetX : 0inch 22 | OffsetY : 0inch 23 | 24 | Plotfile Info: 25 | 26 | Coordinate Format : 2.5 27 | Coordinate Units : Inch 28 | Data Mode : Absolute 29 | Zero Suppression : None 30 | End Of Block : * 31 | 32 | Apertures used: 33 | 34 | Code Shape Size used 35 | 36 | D10 draw 0.0160inch 8 37 | D11 draw 0.0000inch 14 38 | 39 | -------------------------------------------------------------------------------- /Eagle/untitled.bottomlayer.gpi: -------------------------------------------------------------------------------- 1 | Generated by EAGLE CAM Processor 8.2.0 2 | 3 | Photoplotter Info File: d:/git/Domophone/Eagle_v2/untitled.bottomlayer.gpi 4 | 5 | Date : 14.05.2017 22:12 6 | Plotfile : d:/git/Domophone/Eagle_v2/untitled.bottomlayer.ger 7 | Apertures : generated: 8 | Device : Gerber RS-274-X photoplotter, coordinate format 2.5 inch 9 | 10 | Parameter settings: 11 | 12 | Emulate Apertures : no 13 | Tolerance Draw + : 0.00 % 14 | Tolerance Draw - : 0.00 % 15 | Tolerance Flash + : 0.00 % 16 | Tolerance Flash - : 0.00 % 17 | Rotate : no 18 | Mirror : no 19 | Optimize : yes 20 | Auto fit : yes 21 | OffsetX : 0inch 22 | OffsetY : 0inch 23 | 24 | Plotfile Info: 25 | 26 | Coordinate Format : 2.5 27 | Coordinate Units : Inch 28 | Data Mode : Absolute 29 | Zero Suppression : None 30 | End Of Block : * 31 | 32 | Apertures used: 33 | 34 | Code Shape Size used 35 | 36 | D10 round 0.0740inch 30 37 | D11 rectangle 0.0551inch x 0.0394inch 9 38 | D12 rectangle 0.0230inch x 0.0180inch 3 39 | D13 rectangle 0.0591inch x 0.0512inch 10 40 | D14 rectangle 0.0512inch x 0.0591inch 12 41 | D15 round 0.0650inch 10 42 | D16 round 0.0700inch 10 43 | D17 draw 0.0100inch 1789 44 | D18 draw 0.0160inch 69 45 | D19 round 0.0270inch 20 46 | 47 | -------------------------------------------------------------------------------- /Eagle/untitled.bottomsilkscreen.ger: -------------------------------------------------------------------------------- 1 | G75* 2 | %MOIN*% 3 | %OFA0B0*% 4 | %FSLAX25Y25*% 5 | %IPPOS*% 6 | %LPD*% 7 | %AMOC8* 8 | 5,1,8,0,0,1.08239X$1,22.5* 9 | % 10 | M02* 11 | -------------------------------------------------------------------------------- /Eagle/untitled.bottomsilkscreen.gpi: -------------------------------------------------------------------------------- 1 | Generated by EAGLE CAM Processor 8.2.0 2 | 3 | Photoplotter Info File: d:/git/Domophone/Eagle_v2/untitled.bottomsilkscreen.gpi 4 | 5 | Date : 14.05.2017 22:12 6 | Plotfile : d:/git/Domophone/Eagle_v2/untitled.bottomsilkscreen.ger 7 | Apertures : generated: 8 | Device : Gerber RS-274-X photoplotter, coordinate format 2.5 inch 9 | 10 | Parameter settings: 11 | 12 | Emulate Apertures : no 13 | Tolerance Draw + : 0.00 % 14 | Tolerance Draw - : 0.00 % 15 | Tolerance Flash + : 0.00 % 16 | Tolerance Flash - : 0.00 % 17 | Rotate : no 18 | Mirror : no 19 | Optimize : yes 20 | Auto fit : yes 21 | OffsetX : 0inch 22 | OffsetY : 0inch 23 | 24 | Plotfile Info: 25 | 26 | Coordinate Format : 2.5 27 | Coordinate Units : Inch 28 | Data Mode : Absolute 29 | Zero Suppression : None 30 | End Of Block : * 31 | 32 | Apertures used: 33 | 34 | Code Shape Size used 35 | 36 | 37 | -------------------------------------------------------------------------------- /Eagle/untitled.bottomsoldermask.ger: -------------------------------------------------------------------------------- 1 | G75* 2 | %MOIN*% 3 | %OFA0B0*% 4 | %FSLAX25Y25*% 5 | %IPPOS*% 6 | %LPD*% 7 | %AMOC8* 8 | 5,1,8,0,0,1.08239X$1,22.5* 9 | % 10 | %ADD10C,0.10500*% 11 | %ADD11C,0.06500*% 12 | %ADD12C,0.07900*% 13 | %ADD13R,0.06012X0.04437*% 14 | %ADD14R,0.06406X0.05618*% 15 | %ADD15R,0.05618X0.06406*% 16 | %ADD16C,0.06996*% 17 | %ADD17C,0.07500*% 18 | %ADD18C,0.03200*% 19 | D10* 20 | X0015500Y0016500D03* 21 | X0095500Y0016500D03* 22 | X0095500Y0186500D03* 23 | X0015500Y0186500D03* 24 | D11* 25 | X0027500Y0189500D03* 26 | X0037500Y0189500D03* 27 | X0047500Y0189500D03* 28 | X0042500Y0169500D03* 29 | X0032500Y0169500D03* 30 | X0063500Y0189500D03* 31 | X0073500Y0189500D03* 32 | X0083500Y0189500D03* 33 | X0078500Y0169500D03* 34 | X0068500Y0169500D03* 35 | D12* 36 | X0100500Y0171500D03* 37 | X0100500Y0161500D03* 38 | X0100500Y0151500D03* 39 | X0100500Y0141500D03* 40 | X0100500Y0131500D03* 41 | X0100500Y0121500D03* 42 | X0100500Y0111500D03* 43 | X0100500Y0101500D03* 44 | X0100500Y0091500D03* 45 | X0100500Y0081500D03* 46 | X0100500Y0071500D03* 47 | X0100500Y0061500D03* 48 | X0100500Y0051500D03* 49 | X0100500Y0041500D03* 50 | X0100500Y0031500D03* 51 | X0010500Y0031500D03* 52 | X0010500Y0041500D03* 53 | X0010500Y0051500D03* 54 | X0010500Y0061500D03* 55 | X0010500Y0071500D03* 56 | X0010500Y0081500D03* 57 | X0010500Y0091500D03* 58 | X0010500Y0101500D03* 59 | X0010500Y0111500D03* 60 | X0010500Y0121500D03* 61 | X0010500Y0131500D03* 62 | X0010500Y0141500D03* 63 | X0010500Y0151500D03* 64 | X0010500Y0161500D03* 65 | X0010500Y0171500D03* 66 | D13* 67 | X0041169Y0131240D03* 68 | X0041169Y0123760D03* 69 | X0049831Y0127500D03* 70 | X0037831Y0095240D03* 71 | X0037831Y0087760D03* 72 | X0029169Y0091500D03* 73 | X0038831Y0056240D03* 74 | X0038831Y0048760D03* 75 | X0030169Y0052500D03* 76 | D14* 77 | X0048500Y0048760D03* 78 | X0048500Y0056240D03* 79 | X0048500Y0087760D03* 80 | X0048500Y0095240D03* 81 | X0031500Y0123760D03* 82 | X0031500Y0131240D03* 83 | X0022500Y0131240D03* 84 | X0022500Y0123760D03* 85 | X0083500Y0126240D03* 86 | X0083500Y0118760D03* 87 | D15* 88 | X0073240Y0137500D03* 89 | X0075760Y0147500D03* 90 | X0083240Y0147500D03* 91 | X0065760Y0137500D03* 92 | X0066240Y0095500D03* 93 | X0058760Y0095500D03* 94 | X0039240Y0073500D03* 95 | X0031760Y0073500D03* 96 | X0058760Y0056500D03* 97 | X0066240Y0056500D03* 98 | X0035240Y0147500D03* 99 | X0027760Y0147500D03* 100 | D16* 101 | X0020500Y0101500D03* 102 | X0020500Y0071500D03* 103 | X0020500Y0061500D03* 104 | X0020500Y0031500D03* 105 | X0060500Y0031500D03* 106 | X0060500Y0071500D03* 107 | X0090500Y0071500D03* 108 | X0090500Y0061500D03* 109 | X0090500Y0031500D03* 110 | X0090500Y0101500D03* 111 | D17* 112 | X0078500Y0159500D03* 113 | X0068500Y0159500D03* 114 | X0063500Y0179500D03* 115 | X0073500Y0179500D03* 116 | X0083500Y0179500D03* 117 | X0047500Y0179500D03* 118 | X0037500Y0179500D03* 119 | X0027500Y0179500D03* 120 | X0032500Y0159500D03* 121 | X0042500Y0159500D03* 122 | D18* 123 | X0045500Y0139500D03* 124 | X0037500Y0119500D03* 125 | X0044500Y0103500D03* 126 | X0047500Y0073500D03* 127 | X0058500Y0044500D03* 128 | X0072500Y0033500D03* 129 | X0080500Y0053500D03* 130 | X0086500Y0044500D03* 131 | X0069500Y0078500D03* 132 | X0076500Y0098500D03* 133 | X0077500Y0120500D03* 134 | X0073500Y0130500D03* 135 | X0063500Y0128500D03* 136 | X0083500Y0133500D03* 137 | X0086500Y0155500D03* 138 | X0029500Y0139500D03* 139 | X0024500Y0154500D03* 140 | X0020500Y0081500D03* 141 | X0021500Y0047500D03* 142 | X0028500Y0035500D03* 143 | M02* 144 | -------------------------------------------------------------------------------- /Eagle/untitled.bottomsoldermask.gpi: -------------------------------------------------------------------------------- 1 | Generated by EAGLE CAM Processor 8.2.0 2 | 3 | Photoplotter Info File: d:/git/Domophone/Eagle_v2/untitled.bottomsoldermask.gpi 4 | 5 | Date : 14.05.2017 22:12 6 | Plotfile : d:/git/Domophone/Eagle_v2/untitled.bottomsoldermask.ger 7 | Apertures : generated: 8 | Device : Gerber RS-274-X photoplotter, coordinate format 2.5 inch 9 | 10 | Parameter settings: 11 | 12 | Emulate Apertures : no 13 | Tolerance Draw + : 0.00 % 14 | Tolerance Draw - : 0.00 % 15 | Tolerance Flash + : 0.00 % 16 | Tolerance Flash - : 0.00 % 17 | Rotate : no 18 | Mirror : no 19 | Optimize : yes 20 | Auto fit : yes 21 | OffsetX : 0inch 22 | OffsetY : 0inch 23 | 24 | Plotfile Info: 25 | 26 | Coordinate Format : 2.5 27 | Coordinate Units : Inch 28 | Data Mode : Absolute 29 | Zero Suppression : None 30 | End Of Block : * 31 | 32 | Apertures used: 33 | 34 | Code Shape Size used 35 | 36 | D10 round 0.1050inch 4 37 | D11 round 0.0650inch 10 38 | D12 round 0.0790inch 30 39 | D13 rectangle 0.0601inch x 0.0444inch 9 40 | D14 rectangle 0.0641inch x 0.0562inch 10 41 | D15 rectangle 0.0562inch x 0.0641inch 12 42 | D16 round 0.0700inch 10 43 | D17 round 0.0750inch 10 44 | D18 round 0.0320inch 20 45 | 46 | -------------------------------------------------------------------------------- /Eagle/untitled.drills.dri: -------------------------------------------------------------------------------- 1 | Generated by EAGLE CAM Processor 8.2.0 2 | 3 | Drill Station Info File: d:/git/Domophone/Eagle_v2/untitled.drills.dri 4 | 5 | Date : 14.05.2017 22:12 6 | Drills : generated 7 | Device : Excellon drill station, coordinate format 2.4 inch 8 | 9 | Parameter settings: 10 | 11 | Tolerance Drill + : 0.00 % 12 | Tolerance Drill - : 0.00 % 13 | Rotate : no 14 | Mirror : no 15 | Optimize : yes 16 | Auto fit : yes 17 | OffsetX : 0inch 18 | OffsetY : 0inch 19 | Layers : Drills Holes 20 | 21 | Drill File Info: 22 | 23 | Data Mode : Absolute 24 | Units : 1/10000 Inch 25 | 26 | Drills used: 27 | 28 | Code Size used 29 | 30 | T01 0.0130inch 20 31 | T02 0.0400inch 40 32 | T03 0.0433inch 10 33 | T04 0.0600inch 10 34 | T05 0.1000inch 4 35 | 36 | Total number of drills: 84 37 | 38 | Plotfiles: 39 | 40 | d:/git/Domophone/Eagle_v2/untitled.drills.xln 41 | -------------------------------------------------------------------------------- /Eagle/untitled.drills.xln: -------------------------------------------------------------------------------- 1 | % 2 | M48 3 | M72 4 | T01C0.0130 5 | T02C0.0400 6 | T03C0.0433 7 | T04C0.0600 8 | T05C0.1000 9 | % 10 | T01 11 | X2150Y4750 12 | X2850Y3550 13 | X4750Y7350 14 | X4450Y10350 15 | X3750Y11950 16 | X2950Y13950 17 | X2450Y15450 18 | X4550Y13950 19 | X6350Y12850 20 | X7350Y13050 21 | X7750Y12050 22 | X8350Y13350 23 | X8650Y15550 24 | X7650Y9850 25 | X6950Y7850 26 | X8050Y5350 27 | X8650Y4450 28 | X7250Y3350 29 | X5850Y4450 30 | X2050Y8150 31 | T02 32 | X1050Y8150 33 | X1050Y7150 34 | X1050Y6150 35 | X1050Y5150 36 | X1050Y4150 37 | X1050Y3150 38 | X1050Y9150 39 | X1050Y10150 40 | X1050Y11150 41 | X1050Y12150 42 | X1050Y13150 43 | X1050Y14150 44 | X1050Y15150 45 | X1050Y16150 46 | X1050Y17150 47 | X2750Y17950 48 | X3750Y17950 49 | X4750Y17950 50 | X4250Y15950 51 | X3250Y15950 52 | X6350Y17950 53 | X7350Y17950 54 | X8350Y17950 55 | X7850Y15950 56 | X6850Y15950 57 | X10050Y16150 58 | X10050Y15150 59 | X10050Y14150 60 | X10050Y13150 61 | X10050Y12150 62 | X10050Y11150 63 | X10050Y10150 64 | X10050Y9150 65 | X10050Y8150 66 | X10050Y7150 67 | X10050Y6150 68 | X10050Y5150 69 | X10050Y4150 70 | X10050Y3150 71 | X10050Y17150 72 | T03 73 | X9050Y10150 74 | X9050Y7150 75 | X9050Y6150 76 | X9050Y3150 77 | X6050Y3150 78 | X6050Y7150 79 | X2050Y7150 80 | X2050Y6150 81 | X2050Y3150 82 | X2050Y10150 83 | T04 84 | X3250Y16950 85 | X4250Y16950 86 | X3750Y18950 87 | X2750Y18950 88 | X4750Y18950 89 | X6350Y18950 90 | X7350Y18950 91 | X8350Y18950 92 | X7850Y16950 93 | X6850Y16950 94 | T05 95 | X1550Y1650 96 | X9550Y1650 97 | X9550Y18650 98 | X1550Y18650 99 | M30 100 | -------------------------------------------------------------------------------- /Eagle/untitled.toplayer.gpi: -------------------------------------------------------------------------------- 1 | Generated by EAGLE CAM Processor 8.2.0 2 | 3 | Photoplotter Info File: d:/git/Domophone/Eagle_v2/untitled.toplayer.gpi 4 | 5 | Date : 14.05.2017 22:12 6 | Plotfile : d:/git/Domophone/Eagle_v2/untitled.toplayer.ger 7 | Apertures : generated: 8 | Device : Gerber RS-274-X photoplotter, coordinate format 2.5 inch 9 | 10 | Parameter settings: 11 | 12 | Emulate Apertures : no 13 | Tolerance Draw + : 0.00 % 14 | Tolerance Draw - : 0.00 % 15 | Tolerance Flash + : 0.00 % 16 | Tolerance Flash - : 0.00 % 17 | Rotate : no 18 | Mirror : no 19 | Optimize : yes 20 | Auto fit : yes 21 | OffsetX : 0inch 22 | OffsetY : 0inch 23 | 24 | Plotfile Info: 25 | 26 | Coordinate Format : 2.5 27 | Coordinate Units : Inch 28 | Data Mode : Absolute 29 | Zero Suppression : None 30 | End Of Block : * 31 | 32 | Apertures used: 33 | 34 | Code Shape Size used 35 | 36 | D10 round 0.0740inch 30 37 | D11 round 0.0650inch 10 38 | D12 round 0.0700inch 10 39 | D13 rectangle 0.0500inch x 0.0787inch 12 40 | D14 rectangle 0.0709inch x 0.0697inch 4 41 | D15 draw 0.0100inch 1733 42 | D16 round 0.0270inch 20 43 | D17 draw 0.0160inch 89 44 | 45 | -------------------------------------------------------------------------------- /Eagle/untitled.topsilkscreen.ger: -------------------------------------------------------------------------------- 1 | G75* 2 | %MOIN*% 3 | %OFA0B0*% 4 | %FSLAX25Y25*% 5 | %IPPOS*% 6 | %LPD*% 7 | %AMOC8* 8 | 5,1,8,0,0,1.08239X$1,22.5* 9 | % 10 | %ADD10C,0.00800*% 11 | %ADD11C,0.00500*% 12 | %ADD12C,0.00600*% 13 | D10* 14 | X0008000Y0026500D02* 15 | X0005500Y0029000D01* 16 | X0005500Y0034000D01* 17 | X0008000Y0036500D01* 18 | X0005500Y0039000D01* 19 | X0005500Y0044000D01* 20 | X0008000Y0046500D01* 21 | X0005500Y0049000D01* 22 | X0005500Y0054000D01* 23 | X0008000Y0056500D01* 24 | X0005500Y0059000D01* 25 | X0005500Y0064000D01* 26 | X0008000Y0066500D01* 27 | X0005500Y0069000D01* 28 | X0005500Y0074000D01* 29 | X0008000Y0076500D01* 30 | X0005500Y0079000D01* 31 | X0005500Y0084000D01* 32 | X0008000Y0086500D01* 33 | X0005500Y0089000D01* 34 | X0005500Y0094000D01* 35 | X0008000Y0096500D01* 36 | X0005500Y0099000D01* 37 | X0005500Y0104000D01* 38 | X0008000Y0106500D01* 39 | X0005500Y0109000D01* 40 | X0005500Y0114000D01* 41 | X0008000Y0116500D01* 42 | X0005500Y0119000D01* 43 | X0005500Y0124000D01* 44 | X0008000Y0126500D01* 45 | X0005500Y0129000D01* 46 | X0005500Y0134000D01* 47 | X0008000Y0136500D01* 48 | X0005500Y0139000D01* 49 | X0005500Y0144000D01* 50 | X0008000Y0146500D01* 51 | X0005500Y0149000D01* 52 | X0005500Y0154000D01* 53 | X0008000Y0156500D01* 54 | X0005500Y0159000D01* 55 | X0005500Y0164000D01* 56 | X0008000Y0166500D01* 57 | X0005500Y0169000D01* 58 | X0005500Y0174000D01* 59 | X0008000Y0176500D01* 60 | X0013000Y0176500D01* 61 | X0015500Y0174000D01* 62 | X0015500Y0169000D01* 63 | X0013000Y0166500D01* 64 | X0015500Y0164000D01* 65 | X0015500Y0159000D01* 66 | X0013000Y0156500D01* 67 | X0015500Y0154000D01* 68 | X0015500Y0149000D01* 69 | X0013000Y0146500D01* 70 | X0015500Y0144000D01* 71 | X0015500Y0139000D01* 72 | X0013000Y0136500D01* 73 | X0015500Y0134000D01* 74 | X0015500Y0129000D01* 75 | X0013000Y0126500D01* 76 | X0015500Y0124000D01* 77 | X0015500Y0119000D01* 78 | X0013000Y0116500D01* 79 | X0015500Y0114000D01* 80 | X0015500Y0109000D01* 81 | X0013000Y0106500D01* 82 | X0015500Y0104000D01* 83 | X0015500Y0099000D01* 84 | X0013000Y0096500D01* 85 | X0015500Y0094000D01* 86 | X0015500Y0089000D01* 87 | X0013000Y0086500D01* 88 | X0015500Y0084000D01* 89 | X0015500Y0079000D01* 90 | X0013000Y0076500D01* 91 | X0015500Y0074000D01* 92 | X0015500Y0069000D01* 93 | X0013000Y0066500D01* 94 | X0015500Y0064000D01* 95 | X0015500Y0059000D01* 96 | X0013000Y0056500D01* 97 | X0015500Y0054000D01* 98 | X0015500Y0049000D01* 99 | X0013000Y0046500D01* 100 | X0015500Y0044000D01* 101 | X0015500Y0039000D01* 102 | X0013000Y0036500D01* 103 | X0015500Y0034000D01* 104 | X0015500Y0029000D01* 105 | X0013000Y0026500D01* 106 | X0008000Y0026500D01* 107 | X0095500Y0029000D02* 108 | X0098000Y0026500D01* 109 | X0103000Y0026500D01* 110 | X0105500Y0029000D01* 111 | X0105500Y0034000D01* 112 | X0103000Y0036500D01* 113 | X0105500Y0039000D01* 114 | X0105500Y0044000D01* 115 | X0103000Y0046500D01* 116 | X0105500Y0049000D01* 117 | X0105500Y0054000D01* 118 | X0103000Y0056500D01* 119 | X0105500Y0059000D01* 120 | X0105500Y0064000D01* 121 | X0103000Y0066500D01* 122 | X0105500Y0069000D01* 123 | X0105500Y0074000D01* 124 | X0103000Y0076500D01* 125 | X0105500Y0079000D01* 126 | X0105500Y0084000D01* 127 | X0103000Y0086500D01* 128 | X0105500Y0089000D01* 129 | X0105500Y0094000D01* 130 | X0103000Y0096500D01* 131 | X0105500Y0099000D01* 132 | X0105500Y0104000D01* 133 | X0103000Y0106500D01* 134 | X0105500Y0109000D01* 135 | X0105500Y0114000D01* 136 | X0103000Y0116500D01* 137 | X0105500Y0119000D01* 138 | X0105500Y0124000D01* 139 | X0103000Y0126500D01* 140 | X0105500Y0129000D01* 141 | X0105500Y0134000D01* 142 | X0103000Y0136500D01* 143 | X0105500Y0139000D01* 144 | X0105500Y0144000D01* 145 | X0103000Y0146500D01* 146 | X0105500Y0149000D01* 147 | X0105500Y0154000D01* 148 | X0103000Y0156500D01* 149 | X0105500Y0159000D01* 150 | X0105500Y0164000D01* 151 | X0103000Y0166500D01* 152 | X0105500Y0169000D01* 153 | X0105500Y0174000D01* 154 | X0103000Y0176500D01* 155 | X0098000Y0176500D01* 156 | X0095500Y0174000D01* 157 | X0095500Y0169000D01* 158 | X0098000Y0166500D01* 159 | X0095500Y0164000D01* 160 | X0095500Y0159000D01* 161 | X0098000Y0156500D01* 162 | X0095500Y0154000D01* 163 | X0095500Y0149000D01* 164 | X0098000Y0146500D01* 165 | X0095500Y0144000D01* 166 | X0095500Y0139000D01* 167 | X0098000Y0136500D01* 168 | X0095500Y0134000D01* 169 | X0095500Y0129000D01* 170 | X0098000Y0126500D01* 171 | X0095500Y0124000D01* 172 | X0095500Y0119000D01* 173 | X0098000Y0116500D01* 174 | X0095500Y0114000D01* 175 | X0095500Y0109000D01* 176 | X0098000Y0106500D01* 177 | X0095500Y0104000D01* 178 | X0095500Y0099000D01* 179 | X0098000Y0096500D01* 180 | X0095500Y0094000D01* 181 | X0095500Y0089000D01* 182 | X0098000Y0086500D01* 183 | X0095500Y0084000D01* 184 | X0095500Y0079000D01* 185 | X0098000Y0076500D01* 186 | X0095500Y0074000D01* 187 | X0095500Y0069000D01* 188 | X0098000Y0066500D01* 189 | X0095500Y0064000D01* 190 | X0095500Y0059000D01* 191 | X0098000Y0056500D01* 192 | X0095500Y0054000D01* 193 | X0095500Y0049000D01* 194 | X0098000Y0046500D01* 195 | X0095500Y0044000D01* 196 | X0095500Y0039000D01* 197 | X0098000Y0036500D01* 198 | X0095500Y0034000D01* 199 | X0095500Y0029000D01* 200 | D11* 201 | X0095500Y0026500D02* 202 | X0095500Y0066500D01* 203 | X0095500Y0106500D01* 204 | X0015500Y0106500D01* 205 | X0015500Y0066500D01* 206 | X0095500Y0066500D01* 207 | X0015500Y0066500D01* 208 | X0015500Y0026500D01* 209 | X0095500Y0026500D01* 210 | X0077945Y0023815D02* 211 | X0061055Y0023815D01* 212 | X0061035Y0023618D02* 213 | X0061035Y0022437D01* 214 | X0061035Y0014563D02* 215 | X0061035Y0013382D01* 216 | X0061055Y0013185D02* 217 | X0077945Y0013185D01* 218 | X0077965Y0013382D02* 219 | X0077965Y0014563D01* 220 | X0077965Y0022437D02* 221 | X0077965Y0023618D01* 222 | X0071000Y0021500D02* 223 | X0071000Y0015500D01* 224 | X0067500Y0018500D01* 225 | X0071000Y0021500D01* 226 | X0071000Y0021455D02* 227 | X0070948Y0021455D01* 228 | X0071000Y0020957D02* 229 | X0070366Y0020957D01* 230 | X0069785Y0020458D02* 231 | X0071000Y0020458D01* 232 | X0071000Y0019960D02* 233 | X0069203Y0019960D01* 234 | X0068622Y0019461D02* 235 | X0071000Y0019461D01* 236 | X0071000Y0018963D02* 237 | X0068040Y0018963D01* 238 | X0067542Y0018464D02* 239 | X0071000Y0018464D01* 240 | X0071000Y0017966D02* 241 | X0068123Y0017966D01* 242 | X0068705Y0017467D02* 243 | X0071000Y0017467D01* 244 | X0071000Y0016969D02* 245 | X0069286Y0016969D01* 246 | X0069868Y0016470D02* 247 | X0071000Y0016470D01* 248 | X0071000Y0015972D02* 249 | X0070450Y0015972D01* 250 | X0050965Y0014563D02* 251 | X0050965Y0013382D01* 252 | X0050945Y0013185D02* 253 | X0034055Y0013185D01* 254 | X0034035Y0013382D02* 255 | X0034035Y0014563D01* 256 | X0034035Y0022437D02* 257 | X0034035Y0023618D01* 258 | X0034055Y0023815D02* 259 | X0050945Y0023815D01* 260 | X0050965Y0023618D02* 261 | X0050965Y0022437D01* 262 | X0044500Y0018500D02* 263 | X0041000Y0015500D01* 264 | X0041000Y0021500D01* 265 | X0044500Y0018500D01* 266 | X0044458Y0018464D02* 267 | X0041000Y0018464D01* 268 | X0041000Y0017966D02* 269 | X0043877Y0017966D01* 270 | X0043295Y0017467D02* 271 | X0041000Y0017467D01* 272 | X0041000Y0016969D02* 273 | X0042714Y0016969D01* 274 | X0042132Y0016470D02* 275 | X0041000Y0016470D01* 276 | X0041000Y0015972D02* 277 | X0041550Y0015972D01* 278 | X0041000Y0018963D02* 279 | X0043960Y0018963D01* 280 | X0043378Y0019461D02* 281 | X0041000Y0019461D01* 282 | X0041000Y0019960D02* 283 | X0042797Y0019960D01* 284 | X0042215Y0020458D02* 285 | X0041000Y0020458D01* 286 | X0041000Y0020957D02* 287 | X0041634Y0020957D01* 288 | X0041052Y0021455D02* 289 | X0041000Y0021455D01* 290 | D12* 291 | X0052500Y0119000D02* 292 | X0022500Y0119000D01* 293 | X0022500Y0126500D01* 294 | X0022626Y0126502D01* 295 | X0022751Y0126508D01* 296 | X0022876Y0126518D01* 297 | X0023001Y0126532D01* 298 | X0023126Y0126549D01* 299 | X0023250Y0126571D01* 300 | X0023373Y0126596D01* 301 | X0023495Y0126626D01* 302 | X0023616Y0126659D01* 303 | X0023736Y0126696D01* 304 | X0023855Y0126736D01* 305 | X0023972Y0126781D01* 306 | X0024089Y0126829D01* 307 | X0024203Y0126881D01* 308 | X0024316Y0126936D01* 309 | X0024427Y0126995D01* 310 | X0024536Y0127057D01* 311 | X0024643Y0127123D01* 312 | X0024748Y0127192D01* 313 | X0024851Y0127264D01* 314 | X0024952Y0127339D01* 315 | X0025050Y0127418D01* 316 | X0025145Y0127500D01* 317 | X0025238Y0127584D01* 318 | X0025328Y0127672D01* 319 | X0025416Y0127762D01* 320 | X0025500Y0127855D01* 321 | X0025582Y0127950D01* 322 | X0025661Y0128048D01* 323 | X0025736Y0128149D01* 324 | X0025808Y0128252D01* 325 | X0025877Y0128357D01* 326 | X0025943Y0128464D01* 327 | X0026005Y0128573D01* 328 | X0026064Y0128684D01* 329 | X0026119Y0128797D01* 330 | X0026171Y0128911D01* 331 | X0026219Y0129028D01* 332 | X0026264Y0129145D01* 333 | X0026304Y0129264D01* 334 | X0026341Y0129384D01* 335 | X0026374Y0129505D01* 336 | X0026404Y0129627D01* 337 | X0026429Y0129750D01* 338 | X0026451Y0129874D01* 339 | X0026468Y0129999D01* 340 | X0026482Y0130124D01* 341 | X0026492Y0130249D01* 342 | X0026498Y0130374D01* 343 | X0026500Y0130500D01* 344 | X0026498Y0130626D01* 345 | X0026492Y0130751D01* 346 | X0026482Y0130876D01* 347 | X0026468Y0131001D01* 348 | X0026451Y0131126D01* 349 | X0026429Y0131250D01* 350 | X0026404Y0131373D01* 351 | X0026374Y0131495D01* 352 | X0026341Y0131616D01* 353 | X0026304Y0131736D01* 354 | X0026264Y0131855D01* 355 | X0026219Y0131972D01* 356 | X0026171Y0132089D01* 357 | X0026119Y0132203D01* 358 | X0026064Y0132316D01* 359 | X0026005Y0132427D01* 360 | X0025943Y0132536D01* 361 | X0025877Y0132643D01* 362 | X0025808Y0132748D01* 363 | X0025736Y0132851D01* 364 | X0025661Y0132952D01* 365 | X0025582Y0133050D01* 366 | X0025500Y0133145D01* 367 | X0025416Y0133238D01* 368 | X0025328Y0133328D01* 369 | X0025238Y0133416D01* 370 | X0025145Y0133500D01* 371 | X0025050Y0133582D01* 372 | X0024952Y0133661D01* 373 | X0024851Y0133736D01* 374 | X0024748Y0133808D01* 375 | X0024643Y0133877D01* 376 | X0024536Y0133943D01* 377 | X0024427Y0134005D01* 378 | X0024316Y0134064D01* 379 | X0024203Y0134119D01* 380 | X0024089Y0134171D01* 381 | X0023972Y0134219D01* 382 | X0023855Y0134264D01* 383 | X0023736Y0134304D01* 384 | X0023616Y0134341D01* 385 | X0023495Y0134374D01* 386 | X0023373Y0134404D01* 387 | X0023250Y0134429D01* 388 | X0023126Y0134451D01* 389 | X0023001Y0134468D01* 390 | X0022876Y0134482D01* 391 | X0022751Y0134492D01* 392 | X0022626Y0134498D01* 393 | X0022500Y0134500D01* 394 | X0022500Y0142000D01* 395 | X0052500Y0142000D01* 396 | X0052500Y0119000D01* 397 | X0058500Y0119000D02* 398 | X0058500Y0142000D01* 399 | X0088500Y0142000D01* 400 | X0088500Y0134500D01* 401 | X0088374Y0134498D01* 402 | X0088249Y0134492D01* 403 | X0088124Y0134482D01* 404 | X0087999Y0134468D01* 405 | X0087874Y0134451D01* 406 | X0087750Y0134429D01* 407 | X0087627Y0134404D01* 408 | X0087505Y0134374D01* 409 | X0087384Y0134341D01* 410 | X0087264Y0134304D01* 411 | X0087145Y0134264D01* 412 | X0087028Y0134219D01* 413 | X0086911Y0134171D01* 414 | X0086797Y0134119D01* 415 | X0086684Y0134064D01* 416 | X0086573Y0134005D01* 417 | X0086464Y0133943D01* 418 | X0086357Y0133877D01* 419 | X0086252Y0133808D01* 420 | X0086149Y0133736D01* 421 | X0086048Y0133661D01* 422 | X0085950Y0133582D01* 423 | X0085855Y0133500D01* 424 | X0085762Y0133416D01* 425 | X0085672Y0133328D01* 426 | X0085584Y0133238D01* 427 | X0085500Y0133145D01* 428 | X0085418Y0133050D01* 429 | X0085339Y0132952D01* 430 | X0085264Y0132851D01* 431 | X0085192Y0132748D01* 432 | X0085123Y0132643D01* 433 | X0085057Y0132536D01* 434 | X0084995Y0132427D01* 435 | X0084936Y0132316D01* 436 | X0084881Y0132203D01* 437 | X0084829Y0132089D01* 438 | X0084781Y0131972D01* 439 | X0084736Y0131855D01* 440 | X0084696Y0131736D01* 441 | X0084659Y0131616D01* 442 | X0084626Y0131495D01* 443 | X0084596Y0131373D01* 444 | X0084571Y0131250D01* 445 | X0084549Y0131126D01* 446 | X0084532Y0131001D01* 447 | X0084518Y0130876D01* 448 | X0084508Y0130751D01* 449 | X0084502Y0130626D01* 450 | X0084500Y0130500D01* 451 | X0084502Y0130374D01* 452 | X0084508Y0130249D01* 453 | X0084518Y0130124D01* 454 | X0084532Y0129999D01* 455 | X0084549Y0129874D01* 456 | X0084571Y0129750D01* 457 | X0084596Y0129627D01* 458 | X0084626Y0129505D01* 459 | X0084659Y0129384D01* 460 | X0084696Y0129264D01* 461 | X0084736Y0129145D01* 462 | X0084781Y0129028D01* 463 | X0084829Y0128911D01* 464 | X0084881Y0128797D01* 465 | X0084936Y0128684D01* 466 | X0084995Y0128573D01* 467 | X0085057Y0128464D01* 468 | X0085123Y0128357D01* 469 | X0085192Y0128252D01* 470 | X0085264Y0128149D01* 471 | X0085339Y0128048D01* 472 | X0085418Y0127950D01* 473 | X0085500Y0127855D01* 474 | X0085584Y0127762D01* 475 | X0085672Y0127672D01* 476 | X0085762Y0127584D01* 477 | X0085855Y0127500D01* 478 | X0085950Y0127418D01* 479 | X0086048Y0127339D01* 480 | X0086149Y0127264D01* 481 | X0086252Y0127192D01* 482 | X0086357Y0127123D01* 483 | X0086464Y0127057D01* 484 | X0086573Y0126995D01* 485 | X0086684Y0126936D01* 486 | X0086797Y0126881D01* 487 | X0086911Y0126829D01* 488 | X0087028Y0126781D01* 489 | X0087145Y0126736D01* 490 | X0087264Y0126696D01* 491 | X0087384Y0126659D01* 492 | X0087505Y0126626D01* 493 | X0087627Y0126596D01* 494 | X0087750Y0126571D01* 495 | X0087874Y0126549D01* 496 | X0087999Y0126532D01* 497 | X0088124Y0126518D01* 498 | X0088249Y0126508D01* 499 | X0088374Y0126502D01* 500 | X0088500Y0126500D01* 501 | X0088500Y0119000D01* 502 | X0058500Y0119000D01* 503 | X0066000Y0154500D02* 504 | X0063500Y0157000D01* 505 | X0063500Y0162000D01* 506 | X0066000Y0164500D01* 507 | X0071000Y0164500D01* 508 | X0073500Y0162000D01* 509 | X0076000Y0164500D01* 510 | X0081000Y0164500D01* 511 | X0083500Y0162000D01* 512 | X0083500Y0157000D01* 513 | X0081000Y0154500D01* 514 | X0076000Y0154500D01* 515 | X0073500Y0157000D01* 516 | X0071000Y0154500D01* 517 | X0066000Y0154500D01* 518 | X0073500Y0157000D02* 519 | X0073500Y0162000D01* 520 | X0071000Y0174500D02* 521 | X0068500Y0177000D01* 522 | X0066000Y0174500D01* 523 | X0061000Y0174500D01* 524 | X0058500Y0177000D01* 525 | X0058500Y0182000D01* 526 | X0061000Y0184500D01* 527 | X0066000Y0184500D01* 528 | X0068500Y0182000D01* 529 | X0071000Y0184500D01* 530 | X0076000Y0184500D01* 531 | X0078500Y0182000D01* 532 | X0081000Y0184500D01* 533 | X0086000Y0184500D01* 534 | X0088500Y0182000D01* 535 | X0088500Y0177000D01* 536 | X0086000Y0174500D01* 537 | X0081000Y0174500D01* 538 | X0078500Y0177000D01* 539 | X0076000Y0174500D01* 540 | X0071000Y0174500D01* 541 | X0068500Y0177000D02* 542 | X0068500Y0182000D01* 543 | X0078500Y0182000D02* 544 | X0078500Y0177000D01* 545 | X0052500Y0177000D02* 546 | X0050000Y0174500D01* 547 | X0045000Y0174500D01* 548 | X0042500Y0177000D01* 549 | X0040000Y0174500D01* 550 | X0035000Y0174500D01* 551 | X0032500Y0177000D01* 552 | X0030000Y0174500D01* 553 | X0025000Y0174500D01* 554 | X0022500Y0177000D01* 555 | X0022500Y0182000D01* 556 | X0025000Y0184500D01* 557 | X0030000Y0184500D01* 558 | X0032500Y0182000D01* 559 | X0035000Y0184500D01* 560 | X0040000Y0184500D01* 561 | X0042500Y0182000D01* 562 | X0045000Y0184500D01* 563 | X0050000Y0184500D01* 564 | X0052500Y0182000D01* 565 | X0052500Y0177000D01* 566 | X0045000Y0164500D02* 567 | X0047500Y0162000D01* 568 | X0047500Y0157000D01* 569 | X0045000Y0154500D01* 570 | X0040000Y0154500D01* 571 | X0037500Y0157000D01* 572 | X0035000Y0154500D01* 573 | X0030000Y0154500D01* 574 | X0027500Y0157000D01* 575 | X0027500Y0162000D01* 576 | X0030000Y0164500D01* 577 | X0035000Y0164500D01* 578 | X0037500Y0162000D01* 579 | X0040000Y0164500D01* 580 | X0045000Y0164500D01* 581 | X0042500Y0177000D02* 582 | X0042500Y0182000D01* 583 | X0032500Y0182000D02* 584 | X0032500Y0177000D01* 585 | X0037500Y0162000D02* 586 | X0037500Y0157000D01* 587 | M02* 588 | -------------------------------------------------------------------------------- /Eagle/untitled.topsilkscreen.gpi: -------------------------------------------------------------------------------- 1 | Generated by EAGLE CAM Processor 8.2.0 2 | 3 | Photoplotter Info File: d:/git/Domophone/Eagle_v2/untitled.topsilkscreen.gpi 4 | 5 | Date : 14.05.2017 22:12 6 | Plotfile : d:/git/Domophone/Eagle_v2/untitled.topsilkscreen.ger 7 | Apertures : generated: 8 | Device : Gerber RS-274-X photoplotter, coordinate format 2.5 inch 9 | 10 | Parameter settings: 11 | 12 | Emulate Apertures : no 13 | Tolerance Draw + : 0.00 % 14 | Tolerance Draw - : 0.00 % 15 | Tolerance Flash + : 0.00 % 16 | Tolerance Flash - : 0.00 % 17 | Rotate : no 18 | Mirror : no 19 | Optimize : yes 20 | Auto fit : yes 21 | OffsetX : 0inch 22 | OffsetY : 0inch 23 | 24 | Plotfile Info: 25 | 26 | Coordinate Format : 2.5 27 | Coordinate Units : Inch 28 | Data Mode : Absolute 29 | Zero Suppression : None 30 | End Of Block : * 31 | 32 | Apertures used: 33 | 34 | Code Shape Size used 35 | 36 | D10 draw 0.0080inch 184 37 | D11 draw 0.0050inch 50 38 | D12 draw 0.0060inch 86 39 | 40 | -------------------------------------------------------------------------------- /Eagle/untitled.topsoldermask.ger: -------------------------------------------------------------------------------- 1 | G75* 2 | %MOIN*% 3 | %OFA0B0*% 4 | %FSLAX25Y25*% 5 | %IPPOS*% 6 | %LPD*% 7 | %AMOC8* 8 | 5,1,8,0,0,1.08239X$1,22.5* 9 | % 10 | %ADD10C,0.10500*% 11 | %ADD11C,0.06500*% 12 | %ADD12C,0.07900*% 13 | %ADD13C,0.06996*% 14 | %ADD14C,0.07500*% 15 | %ADD15R,0.05500X0.08374*% 16 | %ADD16R,0.07587X0.07469*% 17 | %ADD17C,0.03200*% 18 | D10* 19 | X0015500Y0016500D03* 20 | X0095500Y0016500D03* 21 | X0095500Y0186500D03* 22 | X0015500Y0186500D03* 23 | D11* 24 | X0027500Y0189500D03* 25 | X0037500Y0189500D03* 26 | X0047500Y0189500D03* 27 | X0042500Y0169500D03* 28 | X0032500Y0169500D03* 29 | X0063500Y0189500D03* 30 | X0073500Y0189500D03* 31 | X0083500Y0189500D03* 32 | X0078500Y0169500D03* 33 | X0068500Y0169500D03* 34 | D12* 35 | X0100500Y0171500D03* 36 | X0100500Y0161500D03* 37 | X0100500Y0151500D03* 38 | X0100500Y0141500D03* 39 | X0100500Y0131500D03* 40 | X0100500Y0121500D03* 41 | X0100500Y0111500D03* 42 | X0100500Y0101500D03* 43 | X0100500Y0091500D03* 44 | X0100500Y0081500D03* 45 | X0100500Y0071500D03* 46 | X0100500Y0061500D03* 47 | X0100500Y0051500D03* 48 | X0100500Y0041500D03* 49 | X0100500Y0031500D03* 50 | X0010500Y0031500D03* 51 | X0010500Y0041500D03* 52 | X0010500Y0051500D03* 53 | X0010500Y0061500D03* 54 | X0010500Y0071500D03* 55 | X0010500Y0081500D03* 56 | X0010500Y0091500D03* 57 | X0010500Y0101500D03* 58 | X0010500Y0111500D03* 59 | X0010500Y0121500D03* 60 | X0010500Y0131500D03* 61 | X0010500Y0141500D03* 62 | X0010500Y0151500D03* 63 | X0010500Y0161500D03* 64 | X0010500Y0171500D03* 65 | D13* 66 | X0020500Y0101500D03* 67 | X0020500Y0071500D03* 68 | X0020500Y0061500D03* 69 | X0020500Y0031500D03* 70 | X0060500Y0031500D03* 71 | X0060500Y0071500D03* 72 | X0090500Y0071500D03* 73 | X0090500Y0061500D03* 74 | X0090500Y0031500D03* 75 | X0090500Y0101500D03* 76 | D14* 77 | X0078500Y0159500D03* 78 | X0068500Y0159500D03* 79 | X0063500Y0179500D03* 80 | X0073500Y0179500D03* 81 | X0083500Y0179500D03* 82 | X0047500Y0179500D03* 83 | X0037500Y0179500D03* 84 | X0027500Y0179500D03* 85 | X0032500Y0159500D03* 86 | X0042500Y0159500D03* 87 | D15* 88 | X0047224Y0148217D03* 89 | X0037382Y0148217D03* 90 | X0027539Y0148217D03* 91 | X0027539Y0112783D03* 92 | X0037382Y0112783D03* 93 | X0047224Y0112783D03* 94 | X0063776Y0112783D03* 95 | X0073618Y0112783D03* 96 | X0083461Y0112783D03* 97 | X0083461Y0148217D03* 98 | X0073618Y0148217D03* 99 | X0063776Y0148217D03* 100 | D16* 101 | X0061461Y0018500D03* 102 | X0050539Y0018500D03* 103 | X0034461Y0018500D03* 104 | X0077539Y0018500D03* 105 | D17* 106 | X0072500Y0033500D03* 107 | X0080500Y0053500D03* 108 | X0086500Y0044500D03* 109 | X0069500Y0078500D03* 110 | X0076500Y0098500D03* 111 | X0077500Y0120500D03* 112 | X0073500Y0130500D03* 113 | X0063500Y0128500D03* 114 | X0045500Y0139500D03* 115 | X0037500Y0119500D03* 116 | X0044500Y0103500D03* 117 | X0047500Y0073500D03* 118 | X0058500Y0044500D03* 119 | X0028500Y0035500D03* 120 | X0021500Y0047500D03* 121 | X0020500Y0081500D03* 122 | X0029500Y0139500D03* 123 | X0024500Y0154500D03* 124 | X0083500Y0133500D03* 125 | X0086500Y0155500D03* 126 | M02* 127 | -------------------------------------------------------------------------------- /Eagle/untitled.topsoldermask.gpi: -------------------------------------------------------------------------------- 1 | Generated by EAGLE CAM Processor 8.2.0 2 | 3 | Photoplotter Info File: d:/git/Domophone/Eagle_v2/untitled.topsoldermask.gpi 4 | 5 | Date : 14.05.2017 22:12 6 | Plotfile : d:/git/Domophone/Eagle_v2/untitled.topsoldermask.ger 7 | Apertures : generated: 8 | Device : Gerber RS-274-X photoplotter, coordinate format 2.5 inch 9 | 10 | Parameter settings: 11 | 12 | Emulate Apertures : no 13 | Tolerance Draw + : 0.00 % 14 | Tolerance Draw - : 0.00 % 15 | Tolerance Flash + : 0.00 % 16 | Tolerance Flash - : 0.00 % 17 | Rotate : no 18 | Mirror : no 19 | Optimize : yes 20 | Auto fit : yes 21 | OffsetX : 0inch 22 | OffsetY : 0inch 23 | 24 | Plotfile Info: 25 | 26 | Coordinate Format : 2.5 27 | Coordinate Units : Inch 28 | Data Mode : Absolute 29 | Zero Suppression : None 30 | End Of Block : * 31 | 32 | Apertures used: 33 | 34 | Code Shape Size used 35 | 36 | D10 round 0.1050inch 4 37 | D11 round 0.0650inch 10 38 | D12 round 0.0790inch 30 39 | D13 round 0.0700inch 10 40 | D14 round 0.0750inch 10 41 | D15 rectangle 0.0550inch x 0.0837inch 12 42 | D16 rectangle 0.0759inch x 0.0747inch 4 43 | D17 round 0.0320inch 20 44 | 45 | -------------------------------------------------------------------------------- /Notes/8XRE86N0JH517J9HHI-226x300.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xDWart/Domophone/725107507ecad677b6d9c493ca5921e75af19886/Notes/8XRE86N0JH517J9HHI-226x300.png -------------------------------------------------------------------------------- /Notes/NodeMcu-pinout-600x531.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xDWart/Domophone/725107507ecad677b6d9c493ca5921e75af19886/Notes/NodeMcu-pinout-600x531.jpg -------------------------------------------------------------------------------- /Notes/Note.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xDWart/Domophone/725107507ecad677b6d9c493ca5921e75af19886/Notes/Note.txt -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Domophone 2 | Релейный модуль расширения на NodeMCU для доработки домофона Wi-Fi'ем и протоколом MQTT 3 | 4 | **Eagle** - рабочий проект EagleCAD (v.7.7.0) 5 | 6 | **platformio.ini** - ini-файл проекта в среде PlatformIO (редактор Atom) 7 | 8 | **src/** - исходные коды прошивки 9 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *# 3 | /docs 4 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/CHANGES.txt: -------------------------------------------------------------------------------- 1 | 1.9 2 | * Do not split MQTT packets over multiple calls to _client->write() 3 | * API change: All constructors now require an instance of Client 4 | to be passed in. 5 | * Fixed example to match 1.8 api changes - dpslwk 6 | * Added username/password support - WilHall 7 | * Added publish_P - publishes messages from PROGMEM - jobytaffey 8 | 9 | 1.8 10 | * KeepAlive interval is configurable in PubSubClient.h 11 | * Maximum packet size is configurable in PubSubClient.h 12 | * API change: Return boolean rather than int from various functions 13 | * API change: Length parameter in message callback changed 14 | from int to unsigned int 15 | * Various internal tidy-ups around types 16 | 1.7 17 | * Improved keepalive handling 18 | * Updated to the Arduino-1.0 API 19 | 1.6 20 | * Added the ability to publish a retained message 21 | 22 | 1.5 23 | * Added default constructor 24 | * Fixed compile error when used with arduino-0021 or later 25 | 26 | 1.4 27 | * Fixed connection lost handling 28 | 29 | 1.3 30 | * Fixed packet reading bug in PubSubClient.readPacket 31 | 32 | 1.2 33 | * Fixed compile error when used with arduino-0016 or later 34 | 35 | 36 | 1.1 37 | * Reduced size of library 38 | * Added support for Will messages 39 | * Clarified licensing - see LICENSE.txt 40 | 41 | 42 | 1.0 43 | * Only Quality of Service (QOS) 0 messaging is supported 44 | * The maximum message size, including header, is 128 bytes 45 | * The keepalive interval is set to 30 seconds 46 | * No support for Will messages 47 | 48 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2008-2012 Nicholas O'Leary 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/README.mediawiki: -------------------------------------------------------------------------------- 1 | A client library for the ESP8266 (using the Arduino environment) that provides support for MQTT. 2 | 3 | Modified from Nicholas O'Leary's original for the Arduino + Ethernet shield: http://knolleary.net/arduino-client-for-mqtt/ 4 | 5 | See here for the ESP8266-Arduino work: https://github.com/esp8266/Arduino 6 | 7 | == MQTT version == 8 | 9 | Note that for now PubSubClient requires a broker that supports version '''3.1.1''' of the MQTT standard, '''not 3.1''' or earler. 10 | 11 | For [http://mosquitto.org/ Mosquitto], this means version 1.3 or later. Although version 1.3 only officially supports MQTT 3.1, it does accept the "MQTT" protocol name string in the CONNECT message (MQTT 3.1 uses "MQIsdp"). Version 1.4 is recommended however, as it fully supports MQTT 3.1.1. 12 | 13 | == New features== 14 | 15 | A whole set of [http://imroy.github.io/pubsubclient/namespaceMQTT.html MQTT classes] has been added, one for each message type. This moved a good amount of code out of the PubSubClient class, leaving it to handle the high-level flow of the protocol. The MQTT classes handle getting data into and out of the messages. 16 | 17 | === Setting options on messages === 18 | 19 | The [http://imroy.github.io/pubsubclient/classPubSubClient.html PubSubClient class] operates mostly as it did before. However, the connect(), publish(), subscribe(), and unsubscribe() methods can now take an appropriate MQTT object. This allows extra options to be set e.g QoS on publish, or multiple topics with one (un)subscribe message. 20 | 21 | You can use the MQTT classes and their chainable setter methods like this: 22 | 23 | client.connect(MQTT::Connect("clientId") 24 | .set_clean_session() 25 | .set_will("status", "down") 26 | .set_auth("username", "password) 27 | .set_keepalive(30) 28 | ); 29 | 30 | client.publish(MQTT::Publish("topic", "payload") 31 | .set_retain() 32 | .set_qos(1) 33 | .set_dup() 34 | ); 35 | 36 | client.subscribe(MQTT::Subscribe() 37 | .add_topic("topic1") 38 | .add_topic("topic2", 1) // optional qos value 39 | ); 40 | 41 | client.unsubscribe(MQTT::Unsubscribe() 42 | .add_topic("topic") 43 | ); 44 | 45 | For details see the [http://imroy.github.io/pubsubclient/classMQTT_1_1Connect.html MQTT::Connect], [http://imroy.github.io/pubsubclient/classMQTT_1_1Publish.html MQTT::Publish], [http://imroy.github.io/pubsubclient/classMQTT_1_1Subscribe.html MQTT::Subscribe], and [http://imroy.github.io/pubsubclient/classMQTT_1_1Unsubscribe.html MQTT::Unsubscribe] classes in the Doxygen-generated documentation. 46 | 47 | See also the [[examples/mqtt_auth/mqtt_auth.ino|mqtt_auth]] or [[examples/mqtt_qos/mqtt_qos.ino|mqtt_qos]] example sketches for how this is used. 48 | 49 | === Publishing and receiving large messages === 50 | 51 | Messages are normally held completely in memory. This can obviously be a problem on microcontrollers, with a very limited amount of RAM. To get around this limitation, Publish payloads can be sent or received using callbacks, which have access to the bare network Client object. 52 | 53 | To publish a large payload: 54 | bool write_payload(Client& payload_stream) { 55 | uint8_t buffer[64]; 56 | for (int i = 0; i < 1024; i++) { 57 | // put something in buffer[] 58 | uint32_t sent = payload_stream.write(buffer, 64); 59 | if (sent < 64) 60 | return false; 61 | } 62 | return true; 63 | } 64 | ... 65 | client.publish("topic", write_payload, 64 * 1024); 66 | 67 | Or see the [[examples/mqtt_publish_large/mqtt_publish_large.ino|mqtt_publish_large]] example. 68 | 69 | To receive a large payload: 70 | void recv_payload(const MQTT::Publish& pub) { 71 | if (pub.has_stream()) { 72 | uint8_t buffer[64]; 73 | int read; 74 | while (read = pub.payload_stream()->read(buffer, 64)) { 75 | // Do something with data in buffer 76 | } 77 | pub.payload_stream()->stop(); 78 | } 79 | } 80 | ... 81 | client.set_callback(recv_payload); 82 | client.subscribe("inTopic"); 83 | 84 | Or see the [[examples/mqtt_subscriber/mqtt_subscriber.ino|mqtt_subscriber]] example. 85 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/examples/ESP8266-OTA/ESP8266-OTA.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Test/demonstration of over-the-air update of an ESP8266 using MQTT. 3 | * 4 | * This sketch connects to an MQTT broker and subscribes to a specific topic 5 | * to receive OTA updates on. 6 | * Send the message using the mosquitto tool: 7 | $ mosquitto_pub -h 192.168.1.1 -t 'ota/192.168.1.13' -r -f /tmp/build*.tmp/sensor-node.cpp.bin 8 | * 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | // Replace with your Wifi SSID and passphrase 16 | const char* ssid = "xxxxxxxx"; 17 | const char* pass = "yyyyyyyy"; 18 | 19 | // Replace with the IP address of your MQTT server 20 | IPAddress server_ip(192,168,1,1); 21 | 22 | void setup() { 23 | Serial.begin(115200); 24 | Serial.println(""); 25 | Serial.print("Arduino MQTT OTA Test "); 26 | Serial.println(__TIMESTAMP__); 27 | 28 | Serial.printf("Sketch size: %u\n", ESP.getSketchSize()); 29 | Serial.printf("Free size: %u\n", ESP.getFreeSketchSpace()); 30 | } 31 | 32 | WiFiClient wclient; 33 | PubSubClient client(wclient, server_ip); 34 | 35 | void receive_ota(const MQTT::Publish& pub) { 36 | uint32_t startTime = millis(); 37 | uint32_t size = pub.payload_len(); 38 | if (size == 0) 39 | return; 40 | 41 | Serial.print("Receiving OTA of "); 42 | Serial.print(size); 43 | Serial.println(" bytes..."); 44 | 45 | Serial.setDebugOutput(true); 46 | if (ESP.updateSketch(*pub.payload_stream(), size, true, false)) { 47 | Serial.println("Clearing retained message."); 48 | client.publish(MQTT::Publish(pub.topic(), "") 49 | .set_retain()); 50 | client.disconnect(); 51 | 52 | Serial.printf("Update Success: %u\nRebooting...\n", millis() - startTime); 53 | ESP.restart(); 54 | delay(10000); 55 | } 56 | 57 | Update.printError(Serial); 58 | Serial.setDebugOutput(false); 59 | } 60 | 61 | void loop() { 62 | if (WiFi.status() != WL_CONNECTED) { 63 | Serial.print("Connecting to "); 64 | Serial.print(ssid); 65 | Serial.println("..."); 66 | WiFi.begin(ssid, pass); 67 | if (WiFi.waitForConnectResult() != WL_CONNECTED) 68 | return; 69 | 70 | Serial.print("IP address: "); 71 | Serial.println(WiFi.localIP()); 72 | } 73 | 74 | if (WiFi.status() == WL_CONNECTED) { 75 | if (!client.connected()) { 76 | // Give ourselves a unique client name 77 | if (client.connect(WiFi.macAddress())) { 78 | client.set_callback(receive_ota); // Register our callback for receiving OTA's 79 | IPAddress local = WiFi.localIP(); 80 | String ipaddr = String(local[0]) + "." + String(local[1]) + "." + String(local[2]) + "." + String(local[3]); 81 | String topic = "ota/" + ipaddr; 82 | Serial.print("Subscribing to topic "); 83 | Serial.println(topic); 84 | client.subscribe(topic); 85 | } 86 | } 87 | 88 | if (client.connected()) 89 | client.loop(); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/examples/mqtt_auth/mqtt_auth.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Basic MQTT example with Authentication 3 | 4 | - connects to an MQTT server, providing username 5 | and password 6 | - publishes "hello world" to the topic "outTopic" 7 | - subscribes to the topic "inTopic" 8 | */ 9 | 10 | #include 11 | #include 12 | 13 | const char *ssid = "xxxxxxxx"; // cannot be longer than 32 characters! 14 | const char *pass = "yyyyyyyy"; // 15 | 16 | // Update these with values suitable for your network. 17 | IPAddress server(172, 16, 0, 2); 18 | 19 | void callback(const MQTT::Publish& pub) { 20 | // handle message arrived 21 | } 22 | 23 | WiFiClient wclient; 24 | PubSubClient client(wclient, server); 25 | 26 | void setup() { 27 | // Setup console 28 | Serial.begin(115200); 29 | delay(10); 30 | Serial.println(); 31 | Serial.println(); 32 | } 33 | 34 | void loop() { 35 | if (WiFi.status() != WL_CONNECTED) { 36 | Serial.print("Connecting to "); 37 | Serial.print(ssid); 38 | Serial.println("..."); 39 | WiFi.begin(ssid, pass); 40 | 41 | if (WiFi.waitForConnectResult() != WL_CONNECTED) 42 | return; 43 | Serial.println("WiFi connected"); 44 | } 45 | 46 | if (WiFi.status() == WL_CONNECTED) { 47 | if (!client.connected()) { 48 | Serial.println("Connecting to MQTT server"); 49 | if (client.connect(MQTT::Connect("arduinoClient") 50 | .set_auth("testeruser", "testpass"))) { 51 | Serial.println("Connected to MQTT server"); 52 | client.set_callback(callback); 53 | client.publish("outTopic","hello world"); 54 | client.subscribe("inTopic"); 55 | } else { 56 | Serial.println("Could not connect to MQTT server"); 57 | } 58 | } 59 | 60 | if (client.connected()) 61 | client.loop(); 62 | } 63 | } 64 | 65 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/examples/mqtt_basic/mqtt_basic.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Basic MQTT example 3 | 4 | - connects to an MQTT server 5 | - publishes "hello world" to the topic "outTopic" 6 | - subscribes to the topic "inTopic" 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | const char *ssid = "xxxxxxxx"; // cannot be longer than 32 characters! 13 | const char *pass = "yyyyyyyy"; // 14 | 15 | // Update these with values suitable for your network. 16 | IPAddress server(172, 16, 0, 2); 17 | 18 | void callback(const MQTT::Publish& pub) { 19 | // handle message arrived 20 | } 21 | 22 | WiFiClient wclient; 23 | PubSubClient client(wclient, server); 24 | 25 | void setup() { 26 | // Setup console 27 | Serial.begin(115200); 28 | delay(10); 29 | Serial.println(); 30 | Serial.println(); 31 | 32 | client.set_callback(callback); 33 | } 34 | 35 | void loop() { 36 | if (WiFi.status() != WL_CONNECTED) { 37 | Serial.print("Connecting to "); 38 | Serial.print(ssid); 39 | Serial.println("..."); 40 | WiFi.begin(ssid, pass); 41 | 42 | if (WiFi.waitForConnectResult() != WL_CONNECTED) 43 | return; 44 | Serial.println("WiFi connected"); 45 | } 46 | 47 | if (WiFi.status() == WL_CONNECTED) { 48 | if (!client.connected()) { 49 | if (client.connect("arduinoClient")) { 50 | client.publish("outTopic","hello world"); 51 | client.subscribe("inTopic"); 52 | } 53 | } 54 | 55 | if (client.connected()) 56 | client.loop(); 57 | } 58 | } 59 | 60 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Publishing in the callback 3 | 4 | - connects to an MQTT server 5 | - subscribes to the topic "inTopic" 6 | - when a message is received, republishes it to "outTopic" 7 | 8 | This example shows how to publish messages within the 9 | callback function. The callback function header needs to 10 | be declared before the PubSubClient constructor and the 11 | actual callback defined afterwards. 12 | This ensures the client reference in the callback function 13 | is valid. 14 | 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | const char *ssid = "xxxxxxxx"; // cannot be longer than 32 characters! 21 | const char *pass = "yyyyyyyy"; // 22 | 23 | // Update these with values suitable for your network. 24 | IPAddress server(172, 16, 0, 2); 25 | 26 | WiFiClient wclient; 27 | PubSubClient client(wclient, server); 28 | 29 | // Callback function 30 | void callback(const MQTT::Publish& pub) { 31 | // In order to republish this payload, a copy must be made 32 | // as the orignal payload buffer will be overwritten whilst 33 | // constructing the PUBLISH packet. 34 | 35 | // Copy the payload to a new message 36 | MQTT::Publish newpub("outTopic", pub.payload(), pub.payload_len()); 37 | client.publish(newpub); 38 | } 39 | 40 | void setup() { 41 | // Setup console 42 | Serial.begin(115200); 43 | delay(10); 44 | Serial.println(); 45 | Serial.println(); 46 | } 47 | 48 | void loop() { 49 | if (WiFi.status() != WL_CONNECTED) { 50 | Serial.print("Connecting to "); 51 | Serial.print(ssid); 52 | Serial.println("..."); 53 | WiFi.begin(ssid, pass); 54 | 55 | if (WiFi.waitForConnectResult() != WL_CONNECTED) 56 | return; 57 | Serial.println("WiFi connected"); 58 | } 59 | 60 | if (WiFi.status() == WL_CONNECTED) { 61 | if (!client.connected()) { 62 | if (client.connect("arduinoClient")) { 63 | client.publish("outTopic","hello world"); 64 | client.set_callback(callback); 65 | client.subscribe("inTopic"); 66 | } 67 | } 68 | 69 | if (client.connected()) 70 | client.loop(); 71 | } 72 | } 73 | 74 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/examples/mqtt_publish_large/mqtt_publish_large.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Large publish message MQTT example 3 | 4 | - connects to an MQTT server 5 | - publishes a large string of text to the topic "outTopic" 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | const char *ssid = "xxxxxxxx"; // cannot be longer than 32 characters! 12 | const char *pass = "yyyyyyyy"; // 13 | 14 | // Update these with values suitable for your network. 15 | IPAddress server(172, 16, 0, 2); 16 | 17 | WiFiClient wclient; 18 | PubSubClient client(wclient, server); 19 | 20 | void setup() { 21 | // Setup console 22 | Serial.begin(115200); 23 | delay(10); 24 | Serial.println(); 25 | Serial.println(); 26 | } 27 | 28 | bool write_payload(Client& payload_stream) { 29 | char buf[64]; 30 | memset(buf, 32, 64); 31 | for (int l = 0; l < 1024; l++) { 32 | int len = sprintf(buf, "%d", l); 33 | buf[len] = 32; 34 | buf[63] = '\n'; 35 | uint32_t sent = payload_stream.write((const uint8_t*)buf, 64); 36 | if (sent < 64) 37 | return false; 38 | } 39 | Serial.println("Published large message."); 40 | return true; 41 | } 42 | 43 | void loop() { 44 | if (WiFi.status() != WL_CONNECTED) { 45 | Serial.print("Connecting to "); 46 | Serial.print(ssid); 47 | Serial.println("..."); 48 | WiFi.begin(ssid, pass); 49 | 50 | if (WiFi.waitForConnectResult() != WL_CONNECTED) 51 | return; 52 | Serial.println("WiFi connected"); 53 | } 54 | 55 | if (WiFi.status() == WL_CONNECTED) { 56 | if (!client.connected()) { 57 | if (client.connect("arduinoClient")) { 58 | client.publish("outTopic", write_payload, 65536); 59 | } 60 | } 61 | 62 | if (client.connected()) 63 | client.loop(); 64 | } 65 | } 66 | 67 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/examples/mqtt_qos/mqtt_qos.ino: -------------------------------------------------------------------------------- 1 | /* 2 | MQTT with QoS example 3 | 4 | - connects to an MQTT server 5 | - publishes "hello world" to the topic "outTopic" with a variety of QoS values 6 | 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | const char *ssid = "xxxxxxxx"; // cannot be longer than 32 characters! 13 | const char *pass = "yyyyyyyy"; // 14 | 15 | // Update these with values suitable for your network. 16 | IPAddress server(172, 16, 0, 2); 17 | 18 | void callback(const MQTT::Publish& pub) { 19 | // handle message arrived 20 | } 21 | 22 | WiFiClient wclient; 23 | PubSubClient client(wclient, server); 24 | 25 | void setup() { 26 | // Setup console 27 | Serial.begin(115200); 28 | delay(10); 29 | Serial.println(); 30 | Serial.println(); 31 | } 32 | 33 | void loop() { 34 | if (WiFi.status() != WL_CONNECTED) { 35 | Serial.print("Connecting to "); 36 | Serial.print(ssid); 37 | Serial.println("..."); 38 | WiFi.begin(ssid, pass); 39 | 40 | if (WiFi.waitForConnectResult() != WL_CONNECTED) 41 | return; 42 | Serial.println("WiFi connected"); 43 | } 44 | 45 | if (WiFi.status() == WL_CONNECTED) { 46 | if (!client.connected()) { 47 | if (client.connect("arduinoClient")) { 48 | client.set_callback(callback); 49 | client.publish("outTopic", "hello world qos=0"); // Simple publish with qos=0 50 | 51 | client.publish(MQTT::Publish("outTopic", "hello world qos=1") 52 | .set_qos(1)); 53 | 54 | client.publish(MQTT::Publish("outTopic", "hello world qos=2") 55 | .set_qos(2)); 56 | } 57 | } 58 | 59 | if (client.connected()) 60 | client.loop(); 61 | } 62 | } 63 | 64 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/examples/mqtt_stream/mqtt_stream.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Example of using a Stream object to store the message payload 3 | 4 | Uses SRAM library: https://github.com/ennui2342/arduino-sram 5 | but could use any Stream based class such as SD 6 | 7 | - connects to an MQTT server 8 | - publishes "hello world" to the topic "outTopic" 9 | - subscribes to the topic "inTopic" 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | const char *ssid = "xxxxxxxx"; // cannot be longer than 32 characters! 17 | const char *pass = "yyyyyyyy"; // 18 | 19 | // Update these with values suitable for your network. 20 | IPAddress server(172, 16, 0, 2); 21 | 22 | SRAM sram(4, SRAM_1024); 23 | 24 | void callback(const MQTT::Publish& pub) { 25 | sram.seek(1); 26 | 27 | // do something with the message 28 | for (uint8_t i = 0; i < pub.payload_len(); i++) { 29 | uint8_t byte; 30 | if (pub.has_stream()) 31 | pub.payload_stream()->read(&byte, 1); 32 | else 33 | byte = pub.payload()[i]; 34 | sram.write(byte); 35 | Serial.write(byte); 36 | } 37 | 38 | if (pub.has_stream()) 39 | pub.payload_stream()->stop(); 40 | 41 | Serial.println(); 42 | } 43 | 44 | WiFiClient wclient; 45 | PubSubClient client(wclient, server); 46 | 47 | void setup() { 48 | // Setup console 49 | Serial.begin(115200); 50 | delay(10); 51 | Serial.println(); 52 | Serial.println(); 53 | 54 | sram.begin(); 55 | sram.seek(1); 56 | } 57 | 58 | void loop() { 59 | if (WiFi.status() != WL_CONNECTED) { 60 | Serial.print("Connecting to "); 61 | Serial.print(ssid); 62 | Serial.println("..."); 63 | WiFi.begin(ssid, pass); 64 | 65 | if (WiFi.waitForConnectResult() != WL_CONNECTED) 66 | return; 67 | Serial.println("WiFi connected"); 68 | } 69 | 70 | if (WiFi.status() == WL_CONNECTED) { 71 | if (!client.connected()) { 72 | if (client.connect("arduinoClient")) { 73 | client.set_callback(callback); 74 | client.publish("outTopic","hello world"); 75 | client.subscribe("inTopic"); 76 | } 77 | } 78 | 79 | if (client.connected()) 80 | client.loop(); 81 | } 82 | } 83 | 84 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/examples/mqtt_subscriber/mqtt_subscriber.ino: -------------------------------------------------------------------------------- 1 | /* 2 | MQTT subscriber example 3 | 4 | - connects to an MQTT server 5 | - subscribes to the topic "inTopic" 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | const char *ssid = "xxxxxxxx"; // cannot be longer than 32 characters! 12 | const char *pass = "yyyyyyyy"; // 13 | 14 | // Update these with values suitable for your network. 15 | IPAddress server(172, 16, 0, 2); 16 | 17 | #define BUFFER_SIZE 100 18 | 19 | void callback(const MQTT::Publish& pub) { 20 | Serial.print(pub.topic()); 21 | Serial.print(" => "); 22 | if (pub.has_stream()) { 23 | uint8_t buf[BUFFER_SIZE]; 24 | int read; 25 | while (read = pub.payload_stream()->read(buf, BUFFER_SIZE)) { 26 | Serial.write(buf, read); 27 | } 28 | pub.payload_stream()->stop(); 29 | Serial.println(""); 30 | } else 31 | Serial.println(pub.payload_string()); 32 | } 33 | 34 | WiFiClient wclient; 35 | PubSubClient client(wclient, server); 36 | 37 | void setup() { 38 | // Setup console 39 | Serial.begin(115200); 40 | delay(10); 41 | Serial.println(); 42 | Serial.println(); 43 | } 44 | 45 | void loop() { 46 | if (WiFi.status() != WL_CONNECTED) { 47 | Serial.print("Connecting to "); 48 | Serial.print(ssid); 49 | Serial.println("..."); 50 | WiFi.begin(ssid, pass); 51 | 52 | if (WiFi.waitForConnectResult() != WL_CONNECTED) 53 | return; 54 | Serial.println("WiFi connected"); 55 | } 56 | 57 | if (WiFi.status() == WL_CONNECTED) { 58 | if (!client.connected()) { 59 | if (client.connect("arduinoClient")) { 60 | client.set_callback(callback); 61 | client.subscribe("inTopic"); 62 | } 63 | } 64 | 65 | if (client.connected()) 66 | client.loop(); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/examples/mqtt_will/mqtt_will.ino: -------------------------------------------------------------------------------- 1 | /* 2 | MQTT "will" message example 3 | 4 | - connects to an MQTT server with a will message 5 | - publishes a message 6 | - waits a little bit 7 | - disconnects the socket *without* sending a disconnect packet 8 | 9 | You should see the will message published when we disconnect 10 | */ 11 | 12 | #include 13 | #include 14 | 15 | const char *ssid = "xxxxxxxx"; // cannot be longer than 32 characters! 16 | const char *pass = "yyyyyyyy"; // 17 | 18 | // Update these with values suitable for your network. 19 | IPAddress server(172, 16, 0, 2); 20 | 21 | WiFiClient wclient; 22 | PubSubClient client(wclient, server); 23 | 24 | void setup() { 25 | // Setup console 26 | Serial.begin(115200); 27 | delay(10); 28 | Serial.println(); 29 | Serial.println(); 30 | } 31 | 32 | void loop() { 33 | delay(1000); 34 | 35 | if (WiFi.status() != WL_CONNECTED) { 36 | Serial.print("Connecting to "); 37 | Serial.print(ssid); 38 | Serial.println("..."); 39 | WiFi.begin(ssid, pass); 40 | 41 | if (WiFi.waitForConnectResult() != WL_CONNECTED) 42 | return; 43 | Serial.println("WiFi connected"); 44 | } 45 | 46 | if (WiFi.status() == WL_CONNECTED) { 47 | MQTT::Connect con("arduinoClient"); 48 | con.set_will("test", "I am down."); 49 | // Or to set a binary message: 50 | // char msg[4] = { 0xde, 0xad, 0xbe, 0xef }; 51 | // con.set_will("test", msg, 4); 52 | if (client.connect(con)) { 53 | client.publish("test", "I am up!"); 54 | delay(1000); 55 | wclient.stop(); 56 | } else 57 | Serial.println("MQTT connection failed."); 58 | 59 | delay(10000); 60 | } 61 | } 62 | 63 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For Ultrasound 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | PubSubClient KEYWORD1 10 | 11 | # No namespace support? 12 | MQTT KEYWORD1 13 | message_type KEYWORD1 14 | Message KEYWORD1 15 | Connect KEYWORD1 16 | Publish KEYWORD1 17 | Subscribe KEYWORD1 18 | Unsubscribe KEYWORD1 19 | Ping KEYWORD1 20 | Disconnect KEYWORD1 21 | 22 | 23 | ####################################### 24 | # Methods and Functions (KEYWORD2) 25 | ####################################### 26 | 27 | set_server KEYWORD2 28 | callback KEYWORD2 29 | set_callback KEYWORD2 30 | unset_callback KEYWORD2 31 | set_max_retries KEYWORD2 32 | connect KEYWORD2 33 | disconnect KEYWORD2 34 | publish KEYWORD2 35 | subscribe KEYWORD2 36 | loop KEYWORD2 37 | connected KEYWORD2 38 | 39 | send KEYWORD2 40 | type KEYWORD2 41 | readPacket KEYWORD2 42 | set_clean_session KEYWORD2 43 | unset_clean_session KEYWORD2 44 | set_will KEYWORD2 45 | unset_will KEYWORD2 46 | set_auth KEYWORD2 47 | unset_auth KEYWORD2 48 | keepalive KEYWORD2 49 | set_keepalive KEYWORD2 50 | retain KEYWORD2 51 | set_retain KEYWORD2 52 | unset_retain KEYWORD2 53 | qos KEYWORD2 54 | set_qos KEYWORD2 55 | unset_qos KEYWORD2 56 | dup KEYWORD2 57 | set_dup KEYWORD2 58 | unset_dup KEYWORD2 59 | topic KEYWORD2 60 | payload_string KEYWORD2 61 | payload KEYWORD2 62 | payload_len KEYWORD2 63 | Publish_P KEYWORD2 64 | add_topic KEYWORD2 65 | num_rcs KEYWORD2 66 | rc KEYWORD2 67 | 68 | 69 | ####################################### 70 | # Constants (LITERAL1) 71 | ####################################### 72 | 73 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/library.properties: -------------------------------------------------------------------------------- 1 | name=PubSubClient(imroy) 2 | version=1.99.1 3 | author=Nick O'Leary, Ian Tester 4 | maintainer=Ian Tester 5 | sentence=A library for communicating with MQTT brokers. 6 | paragraph=Supports MQTT 3.1.1. 7 | category=Communication 8 | url=https://github.com/Imroy/pubsubclient 9 | architectures=* 10 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/src/MQTT.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | MQTT.cpp - MQTT packet classes 3 | Copyright (C) 2015 Ian Tester 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #include "MQTT.h" 21 | 22 | namespace MQTT { 23 | //! Write a 16-bit value, big-endian order 24 | void write(uint8_t *buf, uint32_t& bufpos, uint16_t data) { 25 | buf[bufpos++] = data >> 8; 26 | buf[bufpos++] = data & 0xff; 27 | } 28 | 29 | //! Write an arbitrary chunk of data, with 16-bit length first 30 | void write(uint8_t *buf, uint32_t& bufpos, uint8_t *data, uint16_t dlen) { 31 | write(buf, bufpos, dlen); 32 | memcpy(buf + bufpos, data, dlen); 33 | bufpos += dlen; 34 | } 35 | 36 | //! Write a string, with 16-bit length first 37 | void write(uint8_t *buf, uint32_t& bufpos, String str) { 38 | const char* c = str.c_str(); 39 | uint32_t length_pos = bufpos; 40 | bufpos += 2; 41 | uint16_t count = 0; 42 | while (*c) { 43 | buf[bufpos++] = *c++; 44 | count++; 45 | } 46 | write(buf, length_pos, count); 47 | } 48 | 49 | void write_bare_payload(uint8_t *buf, uint32_t& bufpos, uint8_t *data, uint32_t dlen) { 50 | memcpy(buf + bufpos, data, dlen); 51 | bufpos += dlen; 52 | } 53 | 54 | //! Template function to read from a buffer 55 | template 56 | T read(uint8_t *buf, uint32_t& pos); 57 | 58 | template <> 59 | uint8_t read(uint8_t *buf, uint32_t& pos) { 60 | return buf[pos++]; 61 | } 62 | 63 | template <> 64 | uint16_t read(uint8_t *buf, uint32_t& pos) { 65 | uint16_t val = buf[pos++] << 8; 66 | val |= buf[pos++]; 67 | return val; 68 | } 69 | 70 | template <> 71 | String read(uint8_t *buf, uint32_t& pos) { 72 | uint16_t len = read(buf, pos); 73 | String val; 74 | val.reserve(len); 75 | for (uint16_t i = 0; i < len; i++) 76 | val += (char)read(buf, pos); 77 | 78 | return val; 79 | } 80 | 81 | //! Template function to read from a Client object 82 | template 83 | T read(Client& client); 84 | 85 | template <> 86 | uint8_t read(Client& client) { 87 | while(!client.available()) {} 88 | return client.read(); 89 | } 90 | 91 | template <> 92 | uint16_t read(Client& client) { 93 | uint16_t val = read(client) << 8; 94 | val |= read(client); 95 | return val; 96 | } 97 | 98 | template <> 99 | String read(Client& client) { 100 | uint16_t len = read(client); 101 | String val; 102 | val.reserve(len); 103 | for (uint16_t i = 0; i < len; i++) 104 | val += (char)read(client); 105 | 106 | return val; 107 | } 108 | 109 | 110 | // Message class 111 | uint8_t Message::fixed_header_length(uint32_t rlength) const { 112 | if (rlength < 128) 113 | return 2; 114 | else if (rlength < 16384) 115 | return 3; 116 | else if (rlength < 2097152) 117 | return 4; 118 | else 119 | return 5; 120 | } 121 | 122 | void Message::write_fixed_header(uint8_t *buf, uint32_t& bufpos, uint32_t rlength) const { 123 | buf[bufpos] = _type << 4; 124 | 125 | switch (_type) { 126 | case PUBLISH: 127 | buf[bufpos] |= _flags & 0x0f; 128 | break; 129 | case PUBREL: 130 | case SUBSCRIBE: 131 | case UNSUBSCRIBE: 132 | buf[bufpos] |= 0x02; 133 | } 134 | bufpos++; 135 | 136 | // Remaining length 137 | do { 138 | uint8_t digit = rlength & 0x7f; 139 | rlength >>= 7; 140 | if (rlength) 141 | digit |= 0x80; 142 | buf[bufpos++] = digit; 143 | } while (rlength); 144 | } 145 | 146 | void Message::write_packet_id(uint8_t *buf, uint32_t& bufpos) const { 147 | write(buf, bufpos, _packet_id); 148 | } 149 | 150 | bool Message::send(Client& client) { 151 | uint32_t variable_header_len = variable_header_length(); 152 | uint32_t remaining_length = variable_header_len + payload_length(); 153 | uint32_t packet_length = fixed_header_length(remaining_length); 154 | if (_payload_callback == nullptr) 155 | packet_length += remaining_length; 156 | else 157 | packet_length += variable_header_len; 158 | 159 | uint8_t *packet = new uint8_t[packet_length]; 160 | 161 | uint32_t pos = 0; 162 | write_fixed_header(packet, pos, remaining_length); 163 | write_variable_header(packet, pos); 164 | 165 | write_payload(packet, pos); 166 | 167 | uint32_t sent = client.write(const_cast(packet), packet_length); 168 | delete [] packet; 169 | if (sent != packet_length) 170 | return false; 171 | 172 | if (_payload_callback != nullptr) 173 | return _payload_callback(client); 174 | 175 | return true; 176 | } 177 | 178 | 179 | // Parser 180 | Message* readPacket(Client& client) { 181 | // Read type and flags 182 | uint8_t type = read(client); 183 | uint8_t flags = type & 0x0f; 184 | type >>= 4; 185 | 186 | // Read the remaining length 187 | uint32_t remaining_length = 0; 188 | { 189 | uint8_t lenbuf[4], lenlen = 0; 190 | uint8_t shifter = 0; 191 | uint8_t digit; 192 | do { 193 | digit = read(client); 194 | lenbuf[lenlen++] = digit; 195 | remaining_length += (digit & 0x7f) << shifter; 196 | shifter += 7; 197 | } while (digit & 0x80); 198 | } 199 | 200 | // Read variable header and/or payload 201 | uint8_t *remaining_data = nullptr; 202 | if (remaining_length > 0) { 203 | if (remaining_length > MQTT_TOO_BIG) { 204 | switch (type) { 205 | case PUBLISH: 206 | return new Publish(flags, client, remaining_length); 207 | case SUBACK: 208 | return new SubscribeAck(client, remaining_length); 209 | default: 210 | return nullptr; 211 | } 212 | } 213 | 214 | remaining_data = new uint8_t[remaining_length]; 215 | { 216 | uint8_t *read_point = remaining_data; 217 | uint32_t rem = remaining_length; 218 | while (client.available() && rem) { 219 | int read_size = client.read(read_point, rem); 220 | if (read_size == -1) 221 | continue; 222 | rem -= read_size; 223 | read_point += read_size; 224 | } 225 | } 226 | } 227 | 228 | // Use the type value to return an object of the appropriate class 229 | Message *obj; 230 | switch (type) { 231 | case CONNACK: 232 | obj = new ConnectAck(remaining_data, remaining_length); 233 | break; 234 | 235 | case PUBLISH: 236 | obj = new Publish(flags, remaining_data, remaining_length); 237 | break; 238 | 239 | case PUBACK: 240 | obj = new PublishAck(remaining_data, remaining_length); 241 | break; 242 | 243 | case PUBREC: 244 | obj = new PublishRec(remaining_data, remaining_length); 245 | break; 246 | 247 | case PUBREL: 248 | obj = new PublishRel(remaining_data, remaining_length); 249 | break; 250 | 251 | case PUBCOMP: 252 | obj = new PublishComp(remaining_data, remaining_length); 253 | break; 254 | 255 | case SUBACK: 256 | obj = new SubscribeAck(remaining_data, remaining_length); 257 | break; 258 | 259 | case UNSUBACK: 260 | obj = new UnsubscribeAck(remaining_data, remaining_length); 261 | break; 262 | 263 | case PINGREQ: 264 | obj = new Ping; 265 | break; 266 | 267 | case PINGRESP: 268 | obj = new PingResp; 269 | break; 270 | 271 | } 272 | if (remaining_data != nullptr) 273 | delete [] remaining_data; 274 | 275 | return obj; 276 | } 277 | 278 | 279 | // Connect class 280 | Connect::Connect(String cid) : 281 | Message(CONNECT), 282 | _clean_session(true), 283 | _clientid(cid), 284 | _will_message(nullptr), _will_message_len(0), 285 | _keepalive(MQTT_KEEPALIVE) 286 | {} 287 | 288 | Connect& Connect::set_will(String willTopic, String willMessage, uint8_t willQos, bool willRetain) { 289 | _will_topic = willTopic; 290 | _will_qos = willQos; 291 | _will_retain = willRetain; 292 | 293 | if (_will_message != nullptr) 294 | delete [] _will_message; 295 | 296 | _will_message_len = willMessage.length(); 297 | _will_message = new uint8_t[_will_message_len]; 298 | memcpy(_will_message, willMessage.c_str(), _will_message_len); 299 | 300 | return *this; 301 | } 302 | 303 | Connect& Connect::set_will(String willTopic, uint8_t *willMessage, uint16_t willMessageLength, uint8_t willQos, bool willRetain) { 304 | _will_topic = willTopic; 305 | _will_qos = willQos; 306 | _will_retain = willRetain; 307 | 308 | if (_will_message != nullptr) 309 | delete [] _will_message; 310 | 311 | _will_message_len = willMessageLength; 312 | _will_message = new uint8_t[_will_message_len]; 313 | memcpy(_will_message, willMessage, _will_message_len); 314 | 315 | return *this; 316 | } 317 | 318 | Connect::~Connect() { 319 | if (_will_message != nullptr) 320 | delete [] _will_message; 321 | } 322 | 323 | uint32_t Connect::variable_header_length(void) const { 324 | return 10; 325 | } 326 | 327 | void Connect::write_variable_header(uint8_t *buf, uint32_t& bufpos) const { 328 | write(buf, bufpos, "MQTT"); // Protocol name 329 | buf[bufpos++] = 4; // Protocol level 330 | 331 | buf[bufpos] = 0; // Connect flags 332 | if (_clean_session) 333 | buf[bufpos] |= 0x02; 334 | 335 | if (_will_topic.length()) { 336 | buf[bufpos] |= 0x04; 337 | 338 | if (_will_qos > 2) 339 | buf[bufpos] |= 2 << 3; 340 | else 341 | buf[bufpos] |= _will_qos << 3; 342 | buf[bufpos] |= _will_retain << 5; 343 | } 344 | 345 | if (_username.length()) { 346 | buf[bufpos] |= 0x80; 347 | if (_password.length()) 348 | buf[bufpos] |= 0x40; 349 | } 350 | bufpos++; 351 | 352 | write(buf, bufpos, _keepalive); // Keepalive period 353 | } 354 | 355 | uint32_t Connect::payload_length(void) const { 356 | uint32_t len = 2 + _clientid.length(); 357 | if (_will_topic.length()) { 358 | len += 2 + _will_topic.length(); 359 | len += 2 + _will_message_len; 360 | } 361 | if (_username.length()) { 362 | len += 2 + _username.length(); 363 | if (_password.length()) 364 | len += 2 + _password.length(); 365 | } 366 | return len; 367 | } 368 | 369 | void Connect::write_payload(uint8_t *buf, uint32_t& bufpos) const { 370 | write(buf, bufpos, _clientid); 371 | 372 | if (_will_topic.length()) { 373 | write(buf, bufpos, _will_topic); 374 | write(buf, bufpos, _will_message, _will_message_len); 375 | } 376 | 377 | if (_username.length()) { 378 | write(buf, bufpos, _username); 379 | if (_password.length()) 380 | write(buf, bufpos, _password); 381 | } 382 | } 383 | 384 | 385 | // ConnectAck class 386 | ConnectAck::ConnectAck(uint8_t* data, uint32_t length) : 387 | Message(CONNACK) 388 | { 389 | uint32_t pos = 0; 390 | uint8_t reserved = read(data, pos); 391 | _session_present = reserved & 0x01; 392 | _rc = read(data, pos); 393 | } 394 | 395 | 396 | // Publish class 397 | Publish::Publish(String topic, String payload) : 398 | Message(PUBLISH), 399 | _topic(topic), 400 | _payload(nullptr), _payload_len(0), 401 | _payload_mine(false) 402 | { 403 | if (payload.length() > 0) { 404 | _payload = new uint8_t[payload.length()]; 405 | memcpy(_payload, payload.c_str(), payload.length()); 406 | _payload_len = payload.length(); 407 | _payload_mine = true; 408 | } 409 | } 410 | 411 | Publish::Publish(String topic, const __FlashStringHelper* payload) : 412 | Message(PUBLISH), 413 | _topic(topic), 414 | _payload_len(strlen_P((PGM_P)payload)), _payload(new uint8_t[_payload_len + 1]), 415 | _payload_mine(true) 416 | { 417 | strncpy_P((char*)_payload, (PGM_P)payload, _payload_len); 418 | } 419 | 420 | Publish Publish_P(String topic, PGM_P payload, uint32_t length) { 421 | uint8_t *p = new uint8_t[length]; 422 | memcpy_P(p, payload, length); 423 | return Publish(topic, p, length, true); 424 | } 425 | 426 | Publish::Publish(uint8_t flags, uint8_t* data, uint32_t length) : 427 | Message(PUBLISH, flags), 428 | _payload(nullptr), _payload_len(0), 429 | _payload_mine(false) 430 | { 431 | uint32_t pos = 0; 432 | _topic = read(data, pos); 433 | if (qos() > 0) 434 | _packet_id = read(data, pos); 435 | 436 | _payload_len = length - pos; 437 | if (_payload_len > 0) { 438 | _payload = new uint8_t[_payload_len]; 439 | memcpy(_payload, data + pos, _payload_len); 440 | _payload_mine = true; 441 | } 442 | } 443 | 444 | Publish::Publish(String topic, payload_callback_t pcb, uint32_t length) : 445 | Message(PUBLISH), 446 | _topic(topic), 447 | _payload_len(length), 448 | _payload(nullptr), _payload_mine(false) 449 | { 450 | _payload_callback = pcb; 451 | } 452 | 453 | Publish::Publish(uint8_t flags, Client& client, uint32_t remaining_length) : 454 | Message(PUBLISH, flags), 455 | _payload(nullptr), _payload_len(remaining_length), 456 | _payload_mine(false) 457 | { 458 | _stream_client = &client; 459 | 460 | // Read the topic 461 | _topic = read(client); 462 | _payload_len -= 2 + _topic.length(); 463 | 464 | if (qos() > 0) { 465 | // Read the packet id 466 | _packet_id = read(client); 467 | _payload_len -= 2; 468 | } 469 | 470 | // Client stream is now at the start of the payload 471 | } 472 | 473 | Publish::~Publish() { 474 | if ((_payload_mine) && (_payload != nullptr)) 475 | delete [] _payload; 476 | } 477 | 478 | Publish& Publish::set_qos(uint8_t q) { 479 | if (q > 2) 480 | q = 2; 481 | 482 | _flags &= ~0x06; 483 | if (q) { 484 | _flags |= q << 1; 485 | _need_packet_id = true; 486 | } 487 | return *this; 488 | } 489 | 490 | String Publish::payload_string(void) const { 491 | String str; 492 | str.reserve(_payload_len); 493 | for (uint32_t i = 0; i < _payload_len; i++) 494 | str += (char)_payload[i]; 495 | 496 | return str; 497 | } 498 | 499 | uint32_t Publish::variable_header_length(void) const { 500 | return 2 + _topic.length() + (qos() ? 2 : 0); 501 | } 502 | 503 | void Publish::write_variable_header(uint8_t *buf, uint32_t& bufpos) const { 504 | write(buf, bufpos, _topic); 505 | if (qos()) 506 | write_packet_id(buf, bufpos); 507 | } 508 | 509 | uint32_t Publish::payload_length(void) const { 510 | return _payload_len; 511 | } 512 | 513 | void Publish::write_payload(uint8_t *buf, uint32_t& bufpos) const { 514 | if (_payload != nullptr) 515 | write_bare_payload(buf, bufpos, _payload, _payload_len); 516 | } 517 | 518 | message_type Publish::response_type(void) const { 519 | switch (qos()) { 520 | case 0: 521 | return None; 522 | case 1: 523 | return PUBACK; 524 | case 2: 525 | return PUBREC; 526 | } 527 | } 528 | 529 | 530 | // PublishAck class 531 | PublishAck::PublishAck(uint16_t pid) : 532 | Message(PUBACK) 533 | { 534 | _packet_id = pid; 535 | } 536 | 537 | PublishAck::PublishAck(uint8_t* data, uint32_t length) : 538 | Message(PUBACK) 539 | { 540 | uint32_t pos = 0; 541 | _packet_id = read(data, pos); 542 | } 543 | 544 | 545 | // PublishRec class 546 | PublishRec::PublishRec(uint16_t pid) : 547 | Message(PUBREC) 548 | { 549 | _packet_id = pid; 550 | } 551 | 552 | PublishRec::PublishRec(uint8_t* data, uint32_t length) : 553 | Message(PUBREC) 554 | { 555 | uint32_t pos = 0; 556 | _packet_id = read(data, pos); 557 | } 558 | 559 | uint32_t PublishRec::variable_header_length(void) const { 560 | return 2; 561 | } 562 | 563 | void PublishRec::write_variable_header(uint8_t *buf, uint32_t& bufpos) const { 564 | write_packet_id(buf, bufpos); 565 | } 566 | 567 | 568 | // PublishRel class 569 | PublishRel::PublishRel(uint16_t pid) : 570 | Message(PUBREL) 571 | { 572 | _packet_id = pid; 573 | } 574 | 575 | PublishRel::PublishRel(uint8_t* data, uint32_t length) : 576 | Message(PUBREL) 577 | { 578 | uint32_t pos = 0; 579 | _packet_id = read(data, pos); 580 | } 581 | 582 | uint32_t PublishRel::variable_header_length(void) const { 583 | return 2; 584 | } 585 | 586 | void PublishRel::write_variable_header(uint8_t *buf, uint32_t& bufpos) const { 587 | write_packet_id(buf, bufpos); 588 | } 589 | 590 | 591 | // PublishComp class 592 | PublishComp::PublishComp(uint16_t pid) : 593 | Message(PUBCOMP) 594 | { 595 | _packet_id = pid; 596 | } 597 | 598 | PublishComp::PublishComp(uint8_t* data, uint32_t length) : 599 | Message(PUBCOMP) 600 | { 601 | uint32_t pos = 0; 602 | _packet_id = read(data, pos); 603 | } 604 | 605 | uint32_t PublishComp::variable_header_length(void) const { 606 | return 2; 607 | } 608 | 609 | void PublishComp::write_variable_header(uint8_t *buf, uint32_t& bufpos) const { 610 | write_packet_id(buf, bufpos); 611 | } 612 | 613 | 614 | // Subscribe class 615 | Subscribe::Subscribe() : 616 | Message(SUBSCRIBE), 617 | _buffer(nullptr), _buflen(0) 618 | { 619 | _need_packet_id = true; 620 | } 621 | 622 | Subscribe::Subscribe(String topic, uint8_t qos) : 623 | Message(SUBSCRIBE), 624 | _buffer(nullptr), _buflen(0) 625 | { 626 | _need_packet_id = true; 627 | _buffer = (uint8_t*)malloc(2 + topic.length() + 1); 628 | write(_buffer, _buflen, topic); 629 | _buffer[_buflen++] = qos; 630 | } 631 | 632 | Subscribe::~Subscribe() { 633 | free(_buffer); 634 | } 635 | 636 | Subscribe& Subscribe::add_topic(String topic, uint8_t qos) { 637 | _buffer = (uint8_t*)realloc(_buffer, _buflen + 2 + topic.length() + 1); 638 | write(_buffer, _buflen, topic); 639 | _buffer[_buflen++] = qos; 640 | return *this; 641 | } 642 | 643 | uint32_t Subscribe::variable_header_length(void) const { 644 | return 2; 645 | } 646 | 647 | void Subscribe::write_variable_header(uint8_t *buf, uint32_t& bufpos) const { 648 | write_packet_id(buf, bufpos); 649 | } 650 | 651 | uint32_t Subscribe::payload_length(void) const { 652 | return _buflen; 653 | } 654 | 655 | void Subscribe::write_payload(uint8_t *buf, uint32_t& bufpos) const { 656 | if (_buffer != nullptr) 657 | write_bare_payload(buf, bufpos, _buffer, _buflen); 658 | } 659 | 660 | 661 | // SubscribeAck class 662 | SubscribeAck::SubscribeAck(uint8_t* data, uint32_t length) : 663 | Message(SUBACK), 664 | _rcs(nullptr) 665 | { 666 | uint32_t pos = 0; 667 | _packet_id = read(data, pos); 668 | 669 | _num_rcs = length - pos; 670 | if (_num_rcs > 0) { 671 | _rcs = new uint8_t[_num_rcs]; 672 | for (uint32_t i = 0; i < _num_rcs; i++) 673 | _rcs[i] = read(data, pos); 674 | } 675 | } 676 | 677 | SubscribeAck::SubscribeAck(Client& client, uint32_t remaining_length) : 678 | Message(SUBACK), 679 | _rcs(nullptr), 680 | _num_rcs(remaining_length - 2) 681 | { 682 | _stream_client = &client; 683 | 684 | // Read packet id 685 | _packet_id = read(client); 686 | 687 | // Client stream is now at the start of the list of rcs 688 | } 689 | 690 | SubscribeAck::~SubscribeAck() { 691 | if (_rcs != nullptr) 692 | delete [] _rcs; 693 | } 694 | 695 | uint8_t SubscribeAck::next_rc(void) const { 696 | return read(*_stream_client); 697 | } 698 | 699 | 700 | // Unsubscribe class 701 | Unsubscribe::Unsubscribe() : 702 | Message(UNSUBSCRIBE), 703 | _buffer(nullptr), _buflen(0) 704 | { 705 | _need_packet_id = true; 706 | } 707 | 708 | Unsubscribe::Unsubscribe(String topic) : 709 | Message(UNSUBSCRIBE), 710 | _buffer(nullptr), _buflen(0) 711 | { 712 | _need_packet_id = true; 713 | _buffer = (uint8_t*)malloc(2 + topic.length()); 714 | write(_buffer, _buflen, topic); 715 | } 716 | 717 | Unsubscribe::~Unsubscribe() { 718 | free(_buffer); 719 | } 720 | 721 | Unsubscribe& Unsubscribe::add_topic(String topic) { 722 | _buffer = (uint8_t*)realloc(_buffer, _buflen + 2 + topic.length()); 723 | write(_buffer, _buflen, topic); 724 | 725 | return *this; 726 | } 727 | 728 | uint32_t Unsubscribe::variable_header_length(void) const { 729 | return 2; 730 | } 731 | 732 | void Unsubscribe::write_variable_header(uint8_t *buf, uint32_t& bufpos) const { 733 | write_packet_id(buf, bufpos); 734 | } 735 | 736 | uint32_t Unsubscribe::payload_length(void) const { 737 | return _buflen; 738 | } 739 | 740 | void Unsubscribe::write_payload(uint8_t *buf, uint32_t& bufpos) const { 741 | if (_buffer != nullptr) 742 | write_bare_payload(buf, bufpos, _buffer, _buflen); 743 | } 744 | 745 | 746 | // SubscribeAck class 747 | UnsubscribeAck::UnsubscribeAck(uint8_t* data, uint32_t length) : 748 | Message(UNSUBACK) 749 | { 750 | uint32_t pos = 0; 751 | _packet_id = read(data, pos); 752 | } 753 | 754 | 755 | } // namespace MQTT 756 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/src/MQTT.h: -------------------------------------------------------------------------------- 1 | /* 2 | MQTT.h - MQTT packet classes 3 | Copyright (C) 2015 Ian Tester 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #pragma once 21 | 22 | #include 23 | #if defined(ESP8266) || defined(ESP32) 24 | #include 25 | #include 26 | #endif 27 | #include 28 | 29 | // MQTT_KEEPALIVE : keepAlive interval in Seconds 30 | #define MQTT_KEEPALIVE 15 31 | 32 | // Packets larger than this can only be streamed 33 | #ifndef MQTT_TOO_BIG 34 | #define MQTT_TOO_BIG 4096 35 | #endif 36 | 37 | class PubSubClient; 38 | 39 | //! namespace for classes representing MQTT messages 40 | namespace MQTT { 41 | 42 | enum message_type { 43 | None, 44 | CONNECT, // Client request to connect to Server 45 | CONNACK, // Connect Acknowledgment 46 | PUBLISH, // Publish message 47 | PUBACK, // Publish Acknowledgment 48 | PUBREC, // Publish Received (assured delivery part 1) 49 | PUBREL, // Publish Release (assured delivery part 2) 50 | PUBCOMP, // Publish Complete (assured delivery part 3) 51 | SUBSCRIBE, // Client Subscribe request 52 | SUBACK, // Subscribe Acknowledgment 53 | UNSUBSCRIBE, // Client Unsubscribe request 54 | UNSUBACK, // Unsubscribe Acknowledgment 55 | PINGREQ, // PING Request 56 | PINGRESP, // PING Response 57 | DISCONNECT, // Client is Disconnecting 58 | Reserved, // Reserved 59 | }; 60 | 61 | //! The Quality of Service (QoS) level is an agreement between sender and receiver of a message regarding the guarantees of delivering a message. 62 | enum Qos { 63 | QOS0 = 0, //! At most once 64 | QOS1 = 1, //! At least once 65 | QOS2 = 2 //! Exactly once 66 | }; 67 | 68 | #ifdef _GLIBCXX_FUNCTIONAL 69 | typedef std::function payload_callback_t; 70 | #else 71 | typedef bool(*payload_callback_t)(Client&); 72 | #endif 73 | 74 | //! Abstract base class 75 | class Message { 76 | protected: 77 | message_type _type; 78 | uint8_t _flags; 79 | uint16_t _packet_id; //! Not all message types use a packet id, but most do 80 | bool _need_packet_id; 81 | Client* _stream_client; 82 | payload_callback_t _payload_callback; 83 | 84 | //! Private constructor from type and flags 85 | Message(message_type t, uint8_t f = 0) : 86 | _type(t), _flags(f), 87 | _packet_id(0), _need_packet_id(false), 88 | _stream_client(nullptr), 89 | _payload_callback(nullptr) 90 | {} 91 | 92 | //! Virtual destructor 93 | virtual ~Message() {} 94 | 95 | //! Length of the fixed header 96 | /*! 97 | \param rlength Remaining lengh i.e variable header + payload 98 | */ 99 | uint8_t fixed_header_length(uint32_t rlength) const; 100 | 101 | //! Write the fixed header to a buffer 102 | /*! 103 | \param buf Pointer to start of buffer (never advances) 104 | \param bufpos Current position in buffer 105 | \param rlength Remaining lengh i.e variable header + payload 106 | */ 107 | void write_fixed_header(uint8_t *buf, uint32_t& bufpos, uint32_t rlength) const; 108 | 109 | //! Does this message need a packet id before being sent? 110 | bool need_packet_id(void) const { return _need_packet_id; } 111 | 112 | //! Set the packet id 113 | void set_packet_id(uint16_t pid) { _packet_id = pid; } 114 | 115 | //! Write the packet id to a buffer 116 | /*! 117 | \param buf Pointer to start of buffer (never advances) 118 | \param bufpos Current position in buffer 119 | */ 120 | void write_packet_id(uint8_t *buf, uint32_t& bufpos) const; 121 | 122 | //! Length of variable header 123 | virtual uint32_t variable_header_length(void) const { return 0; } 124 | 125 | //! Write variable header 126 | /*! 127 | \param buf Pointer to start of buffer (never advances) 128 | \param bufpos Current position in buffer 129 | */ 130 | virtual void write_variable_header(uint8_t *buf, uint32_t& bufpos) const { } 131 | 132 | //! Length of payload 133 | virtual uint32_t payload_length(void) const { return 0; } 134 | 135 | //! Write payload 136 | /*! 137 | \param buf Pointer to start of buffer (never advances) 138 | \param bufpos Current position in buffer 139 | */ 140 | virtual void write_payload(uint8_t *buf, uint32_t& bufpos) const { } 141 | 142 | //! Message type to expect in response to this message 143 | virtual message_type response_type(void) const { return None; } 144 | 145 | friend PubSubClient; // Just to allow it to call response_type() 146 | 147 | public: 148 | //! Send the message out 149 | bool send(Client& client); 150 | 151 | //! Get the message type 152 | message_type type(void) const { return _type; } 153 | 154 | //! Get the packet id 155 | uint16_t packet_id(void) const { return _packet_id; } 156 | 157 | //! Does this message have a network stream for reading the (large) payload? 158 | bool has_stream(void) const { return _stream_client != nullptr; } 159 | 160 | }; 161 | 162 | //! Parser 163 | /*! 164 | remember to free the object once you're finished with it 165 | */ 166 | Message* readPacket(Client& client); 167 | 168 | 169 | //! Message sent when connecting to a broker 170 | class Connect : public Message { 171 | protected: 172 | bool _clean_session; 173 | uint8_t _will_qos; 174 | bool _will_retain; 175 | 176 | String _clientid; 177 | String _will_topic; 178 | uint8_t *_will_message; 179 | uint16_t _will_message_len; 180 | String _username, _password; 181 | 182 | uint16_t _keepalive; 183 | 184 | uint32_t variable_header_length(void) const; 185 | void write_variable_header(uint8_t *buf, uint32_t& bufpos) const; 186 | uint32_t payload_length(void) const; 187 | void write_payload(uint8_t *buf, uint32_t& bufpos) const; 188 | 189 | message_type response_type(void) const { return CONNACK; } 190 | 191 | public: 192 | //! Connect with a client ID 193 | Connect(String cid); 194 | 195 | //! Set the "clear session" flag 196 | Connect& set_clean_session(bool cs = true) { _clean_session = cs; return *this; } 197 | //! Unset the "clear session" flag 198 | Connect& unset_clean_session(void) { _clean_session = false; return *this; } 199 | 200 | //! Set the "will" flag and associated attributes 201 | Connect& set_will(String willTopic, String willMessage, uint8_t willQos = 0, bool willRetain = false); 202 | //! Set the "will" flag and attributes, with an arbitrary will message 203 | Connect& set_will(String willTopic, uint8_t *willMessage, uint16_t willMessageLength, uint8_t willQos = 0, bool willRetain = false); 204 | //! Unset the "will" flag and associated attributes 205 | Connect& unset_will(void) { _will_topic = ""; return *this; } 206 | 207 | //! Set the username and password for authentication 208 | Connect& set_auth(String u, String p) { _username = u; _password = p; return *this; } 209 | //! Unset the username and password for authentication 210 | Connect& unset_auth(void) { _username = ""; _password = ""; return *this; } 211 | 212 | //! Get the keepalive period 213 | uint16_t keepalive(void) const { return _keepalive; } 214 | //! Set the keepalive period 215 | Connect& set_keepalive(uint16_t k) { _keepalive = k; return *this; } 216 | 217 | ~Connect(); 218 | 219 | }; 220 | 221 | 222 | //! Response to Connect 223 | class ConnectAck : public Message { 224 | private: 225 | bool _session_present; 226 | uint8_t _rc; 227 | 228 | //! Private constructor from a network buffer 229 | ConnectAck(uint8_t* data, uint32_t length); 230 | 231 | friend Message* readPacket(Client& client); 232 | }; 233 | 234 | 235 | //! Publish a payload to a topic 236 | class Publish : public Message { 237 | protected: 238 | String _topic; 239 | uint8_t *_payload; 240 | uint32_t _payload_len; 241 | bool _payload_mine; 242 | 243 | uint32_t variable_header_length(void) const; 244 | void write_variable_header(uint8_t *buf, uint32_t& bufpos) const; 245 | uint32_t payload_length(void) const; 246 | void write_payload(uint8_t *buf, uint32_t& bufpos) const; 247 | 248 | message_type response_type(void) const; 249 | 250 | //! Private constructor from a payload and allowing _payload_mine to be set 251 | Publish(String topic, uint8_t* payload, uint32_t length, bool mine) : 252 | Message(PUBLISH), 253 | _topic(topic), 254 | _payload(payload), _payload_len(length), 255 | _payload_mine(mine) 256 | {} 257 | 258 | //! Private constructor from a network buffer 259 | Publish(uint8_t flags, uint8_t* data, uint32_t length); 260 | 261 | //! Private constructor from a network stream 262 | Publish(uint8_t flags, Client& client, uint32_t remaining_length); 263 | 264 | friend Message* readPacket(Client& client); 265 | 266 | public: 267 | //! Constructor from string payload 268 | /*! 269 | \param topic Topic of this message 270 | \param payload Payload of this message 271 | */ 272 | Publish(String topic, String payload); 273 | 274 | //! Constructor from arbitrary payload 275 | /*! 276 | \param topic Topic of this message 277 | \param payload Pointer to a block of data 278 | \param length The length of the data stored at 'payload' 279 | */ 280 | Publish(String topic, uint8_t* payload, uint32_t length) : 281 | Publish(topic, payload, length, false) 282 | {} 283 | 284 | //! Constructor from a callback 285 | /*! 286 | \param topic Topic of this message 287 | \param pcb A callback function that writes the payload directly to the network Client object 288 | \param length The length of the data that 'pcb' will send 289 | */ 290 | Publish(String topic, payload_callback_t pcb, uint32_t length); 291 | 292 | //! Constructor from a string stored in flash using the F() macro 293 | Publish(String topic, const __FlashStringHelper* payload); 294 | 295 | friend Publish Publish_P(String topic, PGM_P payload, uint32_t length); 296 | 297 | ~Publish(); 298 | 299 | //! Get retain flag 300 | bool retain(void) const { return _flags & 0x01; } 301 | //! Set retain flag 302 | Publish& set_retain(bool r = true) { _flags = (_flags & ~0x01) | r; return *this; } 303 | //! Unset retain flag 304 | Publish& unset_retain(void) { _flags = _flags & ~0x01; return *this; } 305 | 306 | //! Get QoS value 307 | uint8_t qos(void) const { return (_flags >> 1) & 0x03; } 308 | //! Set QoS value 309 | Publish& set_qos(uint8_t q); 310 | //! Unset QoS value 311 | Publish& unset_qos(void) { _flags &= ~0x06; _need_packet_id = false; return *this; } 312 | 313 | //! Get dup flag 314 | bool dup(void) const { return (_flags >> 3) & 0x01; } 315 | //! Set dup flag 316 | Publish& set_dup(bool d = true) { _flags = (_flags & ~0x08) | (d ? 0x08 : 0); return *this; } 317 | //! Unset dup flag 318 | Publish& unset_dup(void) { _flags = _flags & ~0x08; return *this; } 319 | 320 | //! Get the topic string 321 | String topic(void) const { return _topic; } 322 | 323 | //! Get the payload as a string 324 | String payload_string(void) const; 325 | 326 | //! Get the payload pointer 327 | uint8_t* payload(void) const { return _payload; } 328 | //! Get the payload length 329 | uint32_t payload_len(void) const { return _payload_len; } 330 | 331 | //! Get the network stream for reading the payload 332 | Client* payload_stream(void) const { return _stream_client; } 333 | }; 334 | 335 | //! A function made to look like a constructor, reading the payload from flash 336 | Publish Publish_P(String topic, PGM_P payload, uint32_t length); 337 | 338 | 339 | //! Response to Publish when qos == 1 340 | class PublishAck : public Message { 341 | private: 342 | uint32_t variable_header_length(void) const { return sizeof(_packet_id); } 343 | void write_variable_header(uint8_t *buf, uint32_t& bufpos) const { write_packet_id(buf, bufpos); } 344 | 345 | //! Private constructor from a network buffer 346 | PublishAck(uint8_t* data, uint32_t length); 347 | 348 | friend Message* readPacket(Client& client); 349 | 350 | public: 351 | //! Constructor from a packet id 352 | PublishAck(uint16_t pid); 353 | 354 | }; 355 | 356 | 357 | //! First response to Publish when qos == 2 358 | class PublishRec : public Message { 359 | private: 360 | uint32_t variable_header_length(void) const; 361 | void write_variable_header(uint8_t *buf, uint32_t& bufpos) const; 362 | 363 | message_type response_type(void) const { return PUBREL; } 364 | 365 | //! Private constructor from a network buffer 366 | PublishRec(uint8_t* data, uint32_t length); 367 | 368 | friend Message* readPacket(Client& client); 369 | 370 | public: 371 | //! Constructor from a packet id 372 | PublishRec(uint16_t pid); 373 | 374 | }; 375 | 376 | 377 | //! Response to PublishRec 378 | class PublishRel : public Message { 379 | private: 380 | uint32_t variable_header_length(void) const; 381 | void write_variable_header(uint8_t *buf, uint32_t& bufpos) const; 382 | 383 | message_type response_type(void) const { return PUBCOMP; } 384 | 385 | //! Private constructor from a network buffer 386 | PublishRel(uint8_t* data, uint32_t length); 387 | 388 | friend Message* readPacket(Client& client); 389 | 390 | public: 391 | //! Constructor from a packet id 392 | PublishRel(uint16_t pid); 393 | 394 | }; 395 | 396 | 397 | //! Response to PublishRel 398 | class PublishComp : public Message { 399 | private: 400 | uint32_t variable_header_length(void) const; 401 | void write_variable_header(uint8_t *buf, uint32_t& bufpos) const; 402 | 403 | //! Private constructor from a network buffer 404 | PublishComp(uint8_t* data, uint32_t length); 405 | 406 | friend Message* readPacket(Client& client); 407 | 408 | public: 409 | //! Constructor from a packet id 410 | PublishComp(uint16_t pid); 411 | 412 | }; 413 | 414 | 415 | //! Subscribe to one or more topics 416 | class Subscribe : public Message { 417 | private: 418 | uint8_t *_buffer; 419 | uint32_t _buflen; 420 | 421 | uint32_t variable_header_length(void) const; 422 | void write_variable_header(uint8_t *buf, uint32_t& bufpos) const; 423 | uint32_t payload_length(void) const; 424 | void write_payload(uint8_t *buf, uint32_t& bufpos) const; 425 | 426 | message_type response_type(void) const { return SUBACK; } 427 | 428 | public: 429 | //! Constructor that starts an empty list of subscriptions 430 | Subscribe(); 431 | 432 | //! Constructor from a topic and optional QoS level 433 | Subscribe(String topic, uint8_t qos = 0); 434 | 435 | ~Subscribe(); 436 | 437 | //! Add another topic and optional QoS level 438 | Subscribe& add_topic(String topic, uint8_t qos = 0); 439 | 440 | }; 441 | 442 | 443 | //! Response to Subscribe 444 | class SubscribeAck : public Message { 445 | private: 446 | uint8_t *_rcs; 447 | uint32_t _num_rcs; 448 | 449 | //! Private constructor from a network buffer 450 | SubscribeAck(uint8_t* data, uint32_t length); 451 | 452 | //! Private constructor from a network stream 453 | SubscribeAck(Client& client, uint32_t remaining_length); 454 | 455 | friend Message* readPacket(Client& client); 456 | 457 | public: 458 | ~SubscribeAck(); 459 | 460 | //! Get the number of return codes available 461 | uint32_t num_rcs(void) const { return _num_rcs; } 462 | 463 | //! Get a return code 464 | uint8_t rc(uint8_t i) const { return _rcs[i]; } 465 | 466 | //! Get the next return code from a stream 467 | uint8_t next_rc(void) const; 468 | 469 | }; 470 | 471 | 472 | //! Unsubscribe from one or more topics 473 | class Unsubscribe : public Message { 474 | private: 475 | uint8_t *_buffer; 476 | uint32_t _buflen; 477 | 478 | uint32_t variable_header_length(void) const; 479 | void write_variable_header(uint8_t *buf, uint32_t& bufpos) const; 480 | uint32_t payload_length(void) const; 481 | void write_payload(uint8_t *buf, uint32_t& bufpos) const; 482 | 483 | message_type response_type(void) const { return UNSUBACK; } 484 | 485 | public: 486 | //! Constructor that starts with an empty list of unsubscriptions 487 | Unsubscribe(); 488 | 489 | //! Constructor from a topic 490 | Unsubscribe(String topic); 491 | 492 | ~Unsubscribe(); 493 | 494 | //! Add another topic to unsubscribe from 495 | Unsubscribe& add_topic(String topic); 496 | 497 | }; 498 | 499 | 500 | //! Response to Unsubscribe 501 | class UnsubscribeAck : public Message { 502 | private: 503 | //! Private constructor from a network buffer 504 | UnsubscribeAck(uint8_t* data, uint32_t length); 505 | 506 | friend Message* readPacket(Client& client); 507 | 508 | }; 509 | 510 | 511 | //! Ping the broker 512 | class Ping : public Message { 513 | private: 514 | message_type response_type(void) const { return PINGRESP; } 515 | 516 | public: 517 | //! Constructor 518 | Ping() : 519 | Message(PINGREQ) 520 | {} 521 | 522 | }; 523 | 524 | 525 | //! Response to Ping 526 | class PingResp : public Message { 527 | public: 528 | //! Constructor 529 | PingResp() : 530 | Message(PINGRESP) 531 | {} 532 | 533 | }; 534 | 535 | 536 | //! Disconnect from the broker 537 | class Disconnect : public Message { 538 | public: 539 | //! Constructor 540 | Disconnect() : 541 | Message(DISCONNECT) 542 | {} 543 | 544 | }; 545 | 546 | } 547 | 548 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/src/PubSubClient.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | PubSubClient.cpp - A simple client for MQTT. 3 | Nicholas O'Leary 4 | http://knolleary.net 5 | */ 6 | 7 | #include "PubSubClient.h" 8 | #include 9 | 10 | PubSubClient::PubSubClient(Client& c) : 11 | _callback(nullptr), 12 | _client(c), 13 | _max_retries(10), 14 | isSubAckFound(false) 15 | {} 16 | 17 | PubSubClient::PubSubClient(Client& c, IPAddress &ip, uint16_t port) : 18 | _callback(nullptr), 19 | _client(c), 20 | _max_retries(10), 21 | isSubAckFound(false), 22 | server_ip(ip), 23 | server_port(port) 24 | {} 25 | 26 | PubSubClient::PubSubClient(Client& c, String hostname, uint16_t port) : 27 | _callback(nullptr), 28 | _client(c), 29 | _max_retries(10), 30 | isSubAckFound(false), 31 | server_port(port), 32 | server_hostname(hostname) 33 | {} 34 | 35 | PubSubClient& PubSubClient::set_server(IPAddress &ip, uint16_t port) { 36 | server_hostname = ""; 37 | server_ip = ip; 38 | server_port = port; 39 | return *this; 40 | } 41 | 42 | PubSubClient& PubSubClient::set_server(String hostname, uint16_t port) { 43 | server_hostname = hostname; 44 | server_port = port; 45 | return *this; 46 | } 47 | 48 | MQTT::Message* PubSubClient::_recv_message(void) { 49 | MQTT::Message *msg = MQTT::readPacket(_client); 50 | if (msg != nullptr) 51 | lastInActivity = millis(); 52 | return msg; 53 | } 54 | 55 | bool PubSubClient::_send_message(MQTT::Message& msg, bool need_reply) { 56 | MQTT::message_type r_type = msg.response_type(); 57 | 58 | if (msg.need_packet_id()) 59 | msg.set_packet_id(_next_packet_id()); 60 | 61 | uint8_t retries = 0; 62 | send: 63 | if (!msg.send(_client)) { 64 | if (retries < _max_retries) { 65 | retries++; 66 | goto send; 67 | } 68 | return false; 69 | } 70 | lastOutActivity = millis(); 71 | 72 | if (!need_reply || (r_type == MQTT::None)) 73 | return true; 74 | 75 | if (!_wait_for(r_type, msg.packet_id())) { 76 | if (retries < _max_retries) { 77 | retries++; 78 | goto send; 79 | } 80 | return false; 81 | } 82 | return true; 83 | } 84 | 85 | void PubSubClient::_process_message(MQTT::Message* msg) { 86 | switch (msg->type()) { 87 | case MQTT::PUBLISH: 88 | { 89 | MQTT::Publish *pub = static_cast(msg); // RTTI is disabled on embedded, so no dynamic_cast<>() 90 | 91 | if (_callback) 92 | _callback(*pub); 93 | 94 | if (pub->qos() == 1) { 95 | MQTT::PublishAck puback(pub->packet_id()); 96 | _send_message(puback); 97 | 98 | } else if (pub->qos() == 2) { 99 | 100 | { 101 | MQTT::PublishRec pubrec(pub->packet_id()); 102 | if (!_send_message(pubrec, true)) 103 | return; 104 | } 105 | 106 | { 107 | MQTT::PublishComp pubcomp(pub->packet_id()); 108 | _send_message(pubcomp); 109 | } 110 | } 111 | } 112 | break; 113 | 114 | case MQTT::PINGREQ: 115 | { 116 | MQTT::PingResp pr; 117 | _send_message(pr); 118 | } 119 | break; 120 | 121 | case MQTT::PINGRESP: 122 | pingOutstanding = false; 123 | } 124 | } 125 | 126 | bool PubSubClient::_wait_for(MQTT::message_type match_type, uint16_t match_pid) { 127 | while (!_client.available()) { 128 | if (millis() - lastInActivity > keepalive * 1000UL) 129 | return false; 130 | yield(); 131 | } 132 | 133 | while (millis() < lastInActivity + (keepalive * 1000)) { 134 | // Read the packet and check it 135 | MQTT::Message *msg = _recv_message(); 136 | if (msg != nullptr) { 137 | if (msg->type() == match_type) { 138 | uint16_t pid = msg->packet_id(); 139 | delete msg; 140 | if (match_pid) 141 | return pid == match_pid; 142 | return true; 143 | }else if(msg->type() == MQTT::SUBACK){ // if the current message is not the one we want 144 | // Signal that we found a SUBACK message 145 | isSubAckFound = true; 146 | } 147 | 148 | _process_message(msg); 149 | 150 | // After having proceeded new incoming packets, we check if our response as not already been processed 151 | if(match_type == MQTT::SUBACK && isSubAckFound){ 152 | isSubAckFound = false; 153 | // Return false will cause a resend of a SUBSCRIBE message (and so a new chance to get a SUBACK) 154 | return false; 155 | } 156 | 157 | delete msg; 158 | } 159 | 160 | yield(); 161 | } 162 | 163 | return false; 164 | } 165 | 166 | bool PubSubClient::connect(String id) { 167 | MQTT::Connect conn(id); 168 | return connect(conn); 169 | } 170 | 171 | bool PubSubClient::connect(String id, String willTopic, uint8_t willQos, bool willRetain, String willMessage) { 172 | MQTT::Connect conn(id); 173 | if (willTopic.length()) 174 | conn.set_will(willTopic, willMessage, willQos, willRetain); 175 | return connect(conn); 176 | } 177 | 178 | bool PubSubClient::connect(MQTT::Connect &conn) { 179 | if (connected()) 180 | return false; 181 | 182 | int result = 0; 183 | 184 | if (server_hostname.length() > 0) 185 | result = _client.connect(server_hostname.c_str(), server_port); 186 | else 187 | result = _client.connect(server_ip, server_port); 188 | 189 | if (!result) { 190 | _client.stop(); 191 | return false; 192 | } 193 | 194 | pingOutstanding = false; 195 | nextMsgId = 1; // Init the next packet id 196 | lastInActivity = millis(); // Init this so that _wait_for() doesn't think we've already timed-out 197 | keepalive = conn.keepalive(); // Store the keepalive period from this connection 198 | 199 | if (!_send_message(conn, true)) { 200 | _client.stop(); 201 | return false; 202 | } 203 | 204 | return true; 205 | } 206 | 207 | bool PubSubClient::loop() { 208 | if (!connected()) 209 | return false; 210 | 211 | unsigned long t = millis(); 212 | if ((t - lastInActivity > keepalive * 1000UL) || (t - lastOutActivity > keepalive * 1000UL)) { 213 | if (pingOutstanding) { 214 | _client.stop(); 215 | return false; 216 | } else { 217 | MQTT::Ping ping; 218 | if (!_send_message(ping)) 219 | return false; 220 | 221 | lastInActivity = lastOutActivity; 222 | pingOutstanding = true; 223 | } 224 | } 225 | if (_client.available()) { 226 | // Read the packet and check it 227 | MQTT::Message *msg = _recv_message(); 228 | if (msg != nullptr) { 229 | _process_message(msg); 230 | delete msg; 231 | } 232 | } 233 | return true; 234 | } 235 | 236 | bool PubSubClient::publish(String topic, String payload) { 237 | if (!connected()) 238 | return false; 239 | 240 | MQTT::Publish pub(topic, payload); 241 | return publish(pub); 242 | } 243 | 244 | bool PubSubClient::publish(String topic, const uint8_t* payload, uint32_t plength, bool retained) { 245 | if (!connected()) 246 | return false; 247 | 248 | MQTT::Publish pub(topic, const_cast(payload), plength); 249 | pub.set_retain(retained); 250 | return publish(pub); 251 | } 252 | 253 | bool PubSubClient::publish(String topic, MQTT::payload_callback_t pcb, uint32_t length, bool retained) { 254 | if (!connected()) 255 | return false; 256 | 257 | MQTT::Publish pub(topic, pcb, length); 258 | pub.set_retain(retained); 259 | return publish(pub); 260 | } 261 | 262 | bool PubSubClient::publish_P(String topic, PGM_P payload, uint32_t plength, bool retained) { 263 | if (!connected()) 264 | return false; 265 | 266 | MQTT::Publish pub = MQTT::Publish_P(topic, payload, plength); 267 | pub.set_retain(retained); 268 | return publish(pub); 269 | } 270 | 271 | bool PubSubClient::publish(MQTT::Publish &pub) { 272 | if (!connected()) 273 | return false; 274 | 275 | switch (pub.qos()) { 276 | case 0: 277 | return _send_message(pub); 278 | 279 | case 1: 280 | return _send_message(pub, true); 281 | 282 | case 2: 283 | { 284 | if (!_send_message(pub, true)) 285 | return false; 286 | 287 | MQTT::PublishRel pubrel(pub.packet_id()); 288 | return _send_message(pubrel, true); 289 | } 290 | } 291 | return false; 292 | } 293 | 294 | bool PubSubClient::subscribe(String topic, uint8_t qos) { 295 | if (!connected()) 296 | return false; 297 | 298 | if (qos > 2) 299 | return false; 300 | 301 | MQTT::Subscribe sub(topic, qos); 302 | return subscribe(sub); 303 | } 304 | 305 | bool PubSubClient::subscribe(MQTT::Subscribe &sub) { 306 | if (!connected()) 307 | return false; 308 | 309 | return _send_message(sub, true); 310 | } 311 | 312 | bool PubSubClient::unsubscribe(String topic) { 313 | if (!connected()) 314 | return false; 315 | 316 | MQTT::Unsubscribe unsub(topic); 317 | return unsubscribe(unsub); 318 | } 319 | 320 | bool PubSubClient::unsubscribe(MQTT::Unsubscribe &unsub) { 321 | if (!connected()) 322 | return false; 323 | 324 | return _send_message(unsub, true); 325 | } 326 | 327 | void PubSubClient::disconnect() { 328 | if (!connected()) 329 | return; 330 | 331 | MQTT::Disconnect discon; 332 | if (_send_message(discon)) 333 | lastInActivity = lastOutActivity; 334 | _client.stop(); 335 | } 336 | 337 | bool PubSubClient::connected() { 338 | bool rc = _client.connected(); 339 | if (!rc) 340 | _client.stop(); 341 | 342 | return rc; 343 | } 344 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/src/PubSubClient.h: -------------------------------------------------------------------------------- 1 | /* 2 | PubSubClient.h - A simple client for MQTT. 3 | Nicholas O'Leary 4 | http://knolleary.net 5 | */ 6 | 7 | #ifndef PubSubClient_h 8 | #define PubSubClient_h 9 | 10 | #if defined(ESP8266) || defined(ESP32) 11 | #include 12 | #include 13 | #endif 14 | 15 | #include 16 | 17 | #include "MQTT.h" 18 | 19 | //! Main do-everything class that sketches will use 20 | class PubSubClient { 21 | public: 22 | #ifdef _GLIBCXX_FUNCTIONAL 23 | typedef std::function callback_t; 24 | #else 25 | typedef void(*callback_t)(const MQTT::Publish&); 26 | #endif 27 | 28 | private: 29 | IPAddress server_ip; 30 | String server_hostname; 31 | uint16_t server_port; 32 | callback_t _callback; 33 | 34 | Client &_client; 35 | uint16_t nextMsgId, keepalive; 36 | uint8_t _max_retries; 37 | unsigned long lastOutActivity; 38 | unsigned long lastInActivity; 39 | bool pingOutstanding; 40 | bool isSubAckFound; 41 | 42 | //! Receive a message from the client 43 | /*! 44 | \return Pointer to message object, nullptr if no message has been received 45 | */ 46 | MQTT::Message* _recv_message(void); 47 | 48 | //! Send a message and wait for its response message (if it has one) 49 | /*! 50 | \param msg The message to send 51 | \param need_reply Do we wait for the reply message? 52 | */ 53 | bool _send_message(MQTT::Message& msg, bool need_reply = false); 54 | 55 | //! Process incoming messages 56 | /*! 57 | - Calls the callback function when a PUBLISH message comes in 58 | - Handles the handshake for PUBLISH when qos > 0 59 | - Handles ping requests and responses 60 | \param msg Message to process 61 | */ 62 | void _process_message(MQTT::Message* msg); 63 | 64 | //! Wait for a certain type of packet to come back, optionally check its packet id 65 | /*! 66 | Other packets are handed over to _process_message() 67 | \param wait_type Message type to match on 68 | \param wait_pid Message packet id to match on 69 | \return True if we received the packet we wanted 70 | */ 71 | bool _wait_for(MQTT::message_type wait_type, uint16_t wait_pid = 0); 72 | 73 | //! Return the next packet id 74 | uint16_t _next_packet_id(void) { 75 | nextMsgId++; 76 | if (nextMsgId == 0) nextMsgId = 1; 77 | return nextMsgId; 78 | } 79 | 80 | public: 81 | //! Simple constructor 82 | /*! 83 | Use set_server() before connect() 84 | */ 85 | PubSubClient(Client& c); 86 | 87 | //! Constructor with the server ip address 88 | PubSubClient(Client& c, IPAddress &ip, uint16_t port = 1883); 89 | //! Constructors with the host name 90 | PubSubClient(Client& c, String hostname, uint16_t port = 1883); 91 | 92 | //! Set the server ip address 93 | PubSubClient& set_server(IPAddress &ip, uint16_t port = 1883); 94 | //! Set the server host name 95 | PubSubClient& set_server(String hostname, uint16_t port = 1883); 96 | 97 | //! Get the callback function 98 | callback_t callback(void) const { return _callback; } 99 | //! Set the callback function 100 | PubSubClient& set_callback(callback_t cb) { _callback = cb; return *this; } 101 | //! Unset the callback function 102 | PubSubClient& unset_callback(void) { _callback = nullptr; return * this; } 103 | 104 | //! Set the maximum number of retries when waiting for response packets 105 | PubSubClient& set_max_retries(uint8_t mr) { _max_retries = mr; return *this; } 106 | 107 | //! Connect to the server with a client id 108 | /*! 109 | \param id Client id for this device 110 | */ 111 | bool connect(String id); 112 | 113 | //! Connect to the server with a client id and "will" parameters 114 | /*! 115 | The "will" is a message that is published when this client *unexpectantly* 116 | disconnects from the broker i.e without sending a DISCONNECT message. 117 | \param id Client id for this device 118 | \param willTopic Topic of the "will" message 119 | \param willQos QoS level of the "will" message 120 | \param willRetain Retain setting of the "will" message 121 | \param willMessage Content (payload) of the "will" message 122 | */ 123 | bool connect(String id, String willTopic, uint8_t willQos, bool willRetain, String willMessage); 124 | 125 | //! Disconnect from the server 126 | void disconnect(void); 127 | 128 | //! Publish a string payload 129 | /*! 130 | \param topic Topic of the message 131 | \param payload String text of the message 132 | */ 133 | bool publish(String topic, String payload); 134 | 135 | //! Publish an arbitrary data payload 136 | /*! 137 | \param topic Topic of the message 138 | \param payload Pointer to contents of the message 139 | \param plength Length of the message (pointed to by payload) in bytes 140 | \param retained If true, this message will be stored on the server and 141 | supplied to any future subscribers whose subscriptions match its topic 142 | name. 143 | */ 144 | bool publish(String topic, const uint8_t *payload, uint32_t plength, bool retained = false); 145 | 146 | //! Publish an arbitrary data payload from a callback 147 | /*! 148 | \param topic Topic of this message 149 | \param pcb A callback function that writes the payload directly to the network Client object 150 | \param length The length of the data that 'pcb' will send 151 | */ 152 | bool publish(String topic, MQTT::payload_callback_t pcb, uint32_t length, bool retained = false); 153 | 154 | //! Publish an arbitrary data payload stored in "program" memory 155 | /*! 156 | \param topic Topic of the message 157 | \param payload Pointer to contents of the message, stored in "program" memory 158 | \param plength Length of the message (pointed to by payload) in bytes 159 | \param retained If true, this message will be stored on the server and 160 | supplied to any future subscribers whose subscriptions match its topic 161 | name. 162 | */ 163 | bool publish_P(String topic, PGM_P payload, uint32_t plength, bool retained = false); 164 | 165 | //! Subscribe to a topic 166 | /*! 167 | \param topic Topic filter 168 | \param qos QoS value. 0 => no handshake, 1 => single handshake, 2 => two-way handshake 169 | */ 170 | bool subscribe(String topic, uint8_t qos = 0); 171 | 172 | //! Unsubscribe from a topic 173 | bool unsubscribe(String topic); 174 | 175 | //! Wait for packets to come in, processing them 176 | /*! 177 | Also periodically pings the server 178 | */ 179 | bool loop(); 180 | 181 | //! Are we connected? 182 | bool connected(); 183 | 184 | //! Connect with a pre-constructed MQTT message object 185 | bool connect(MQTT::Connect &conn); 186 | //! Publish with a pre-constructed MQTT message object 187 | bool publish(MQTT::Publish &pub); 188 | //! Subscribe with a pre-constructed MQTT message object 189 | bool subscribe(MQTT::Subscribe &sub); 190 | //! Unsubscribe with a pre-constructed MQTT message object 191 | bool unsubscribe(MQTT::Unsubscribe &unsub); 192 | }; 193 | 194 | 195 | #endif 196 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/src/PubSubClient_JSON.h: -------------------------------------------------------------------------------- 1 | /* 2 | PubSubClient_JSON.h - ArduinoJson support for PubSubClient 3 | Copyright (C) 2016 Ian Tester 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #pragma once 21 | 22 | #include 23 | 24 | namespace MQTT { 25 | class ConnectJSON : public Connect { 26 | public: 27 | //! Set the "will" flag and attributes, with a JSON object "will" message 28 | template 29 | Connect& set_will(String willTopic, ArduinoJson::Internals::JsonPrintable& willMessage, uint8_t willQos, bool willRetain) { 30 | _will_topic = willTopic; 31 | _will_qos = willQos; 32 | _will_retain = willRetain; 33 | 34 | if (_will_message != nullptr) 35 | delete [] _will_message; 36 | 37 | _will_message_len = willMessage.measureLength() + 1; 38 | _will_message = new uint8_t[_will_message_len]; 39 | if (_will_message != nullptr) 40 | willMessage.printTo((char*)_will_message, _will_message_len); 41 | 42 | return *this; 43 | } 44 | 45 | }; 46 | 47 | class PublishJSON : public Publish { 48 | public: 49 | //! Publish a JSON object from the ArduinoJson library 50 | /*! 51 | \param topic Topic of the message 52 | \param payload Object of the message 53 | */ 54 | template 55 | PublishJSON(String topic, ArduinoJson::Internals::JsonPrintable& object) : 56 | Publish(topic, nullptr, object.measureLength() + 1) 57 | { 58 | _payload = new uint8_t[_payload_len]; 59 | if (_payload != nullptr) 60 | object.printTo((char*)_payload, _payload_len); 61 | } 62 | 63 | }; 64 | 65 | }; 66 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/tests/.gitignore: -------------------------------------------------------------------------------- 1 | .build 2 | tmpbin 3 | logs 4 | *.pyc 5 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/tests/Makefile: -------------------------------------------------------------------------------- 1 | SRC_PATH=./src 2 | OUT_PATH=./bin 3 | TEST_SRC=$(wildcard ${SRC_PATH}/*_spec.cpp) 4 | TEST_BIN= $(TEST_SRC:${SRC_PATH}/%.cpp=${OUT_PATH}/%) 5 | VPATH=${SRC_PATH} 6 | SHIM_FILES=${SRC_PATH}/lib/*.cpp 7 | PSC_FILE=../PubSubClient/PubSubClient.cpp 8 | CC=g++ 9 | CFLAGS=-I${SRC_PATH}/lib -I../PubSubClient 10 | 11 | all: $(TEST_BIN) 12 | 13 | ${OUT_PATH}/%: ${SRC_PATH}/%.cpp ${PSC_FILE} ${SHIM_FILES} 14 | mkdir -p ${OUT_PATH} 15 | ${CC} ${CFLAGS} $^ -o $@ 16 | 17 | clean: 18 | @rm -rf ${OUT_PATH} 19 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/tests/README.md: -------------------------------------------------------------------------------- 1 | # Arduino Client for MQTT Test Suite 2 | 3 | This is a regression test suite for the `PubSubClient` library. 4 | 5 | There are two parts: 6 | 7 | - Tests that can be compiled and run on any machine 8 | - Tests that build the example sketches using the Arduino IDE 9 | 10 | 11 | It is a work-in-progress and is subject to complete refactoring as the whim takes 12 | me. 13 | 14 | 15 | ## Local tests 16 | 17 | These are a set of executables that can be run to test specific areas of functionality. 18 | They do not require a real Arduino to be attached, nor the use of the Arduino IDE. 19 | 20 | The tests include a set of mock files to stub out the parts of the Arduino environment the library 21 | depends on. 22 | 23 | ### Dependencies 24 | 25 | - g++ 26 | 27 | ### Running 28 | 29 | Build the tests using the provided `Makefile`: 30 | 31 | $ make 32 | 33 | This will create a set of executables in `./bin/`. Run each of these executables to test the corresponding functionality. 34 | 35 | *Note:* the `connect_spec` and `keepalive_spec` tests involve testing keepalive timers so naturally take a few minutes to run through. 36 | 37 | ## Arduino tests 38 | 39 | *Note:* INO Tool doesn't currently play nicely with Arduino 1.5. This has broken this test suite. 40 | 41 | Without a suitable arduino plugged in, the test suite will only check the 42 | example sketches compile cleanly against the library. 43 | 44 | With an arduino plugged in, each sketch that has a corresponding python 45 | test case is built, uploaded and then the tests run. 46 | 47 | ### Dependencies 48 | 49 | - Python 2.7+ 50 | - [INO Tool](http://inotool.org/) - this provides command-line build/upload of Arduino sketches 51 | 52 | ### Running 53 | 54 | The test suite _does not_ run an MQTT server - it is assumed to be running already. 55 | 56 | $ python testsuite.py 57 | 58 | A summary of activity is printed to the console. More comprehensive logs are written 59 | to the `logs` directory. 60 | 61 | ### What it does 62 | 63 | For each sketch in the library's `examples` directory, e.g. `mqtt_basic.ino`, the suite looks for a matching test case 64 | `testcases/mqtt_basic.py`. 65 | 66 | The test case must follow these conventions: 67 | - sub-class `unittest.TestCase` 68 | - provide the class methods `setUpClass` and `tearDownClass` (TODO: make this optional) 69 | - all test method names begin with `test_` 70 | 71 | The suite will call the `setUpClass` method _before_ uploading the sketch. This 72 | allows any test setup to be performed before the sketch runs - such as connecting 73 | a client and subscribing to topics. 74 | 75 | 76 | ### Settings 77 | 78 | The file `testcases/settings.py` is used to config the test environment. 79 | 80 | - `server_ip` - the IP address of the broker the client should connect to (the broker port is assumed to be 1883). 81 | - `arduino_ip` - the IP address the arduino should use (when not testing DHCP). 82 | 83 | Before each sketch is compiled, these values are automatically substituted in. To 84 | do this, the suite looks for lines that _start_ with the following: 85 | 86 | byte server[] = { 87 | byte ip[] = { 88 | 89 | and replaces them with the appropriate values. 90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/tests/src/connect_spec.cpp: -------------------------------------------------------------------------------- 1 | #include "PubSubClient.h" 2 | #include "ShimClient.h" 3 | #include "Buffer.h" 4 | #include "BDDTest.h" 5 | #include "trace.h" 6 | 7 | 8 | byte server[] = { 172, 16, 0, 2 }; 9 | 10 | void callback(char* topic, byte* payload, unsigned int length) { 11 | // handle message arrived 12 | } 13 | 14 | 15 | int test_connect_fails_no_network() { 16 | IT("fails to connect if underlying client doesn't connect"); 17 | ShimClient shimClient; 18 | shimClient.setAllowConnect(false); 19 | PubSubClient client(server, 1883, callback, shimClient); 20 | int rc = client.connect((char*)"client_test1"); 21 | IS_FALSE(rc); 22 | END_IT 23 | } 24 | 25 | int test_connect_fails_on_no_response() { 26 | IT("fails to connect if no response received after 15 seconds"); 27 | ShimClient shimClient; 28 | shimClient.setAllowConnect(true); 29 | PubSubClient client(server, 1883, callback, shimClient); 30 | int rc = client.connect((char*)"client_test1"); 31 | IS_FALSE(rc); 32 | END_IT 33 | } 34 | 35 | int test_connect_properly_formatted() { 36 | IT("sends a properly formatted connect packet and succeeds"); 37 | ShimClient shimClient; 38 | 39 | shimClient.setAllowConnect(true); 40 | byte expectServer[] = { 172, 16, 0, 2 }; 41 | shimClient.expectConnect(expectServer,1883); 42 | byte connect[] = {0x10,0x1a,0x0,0x6,0x4d,0x51,0x49,0x73,0x64,0x70,0x3,0x2,0x0,0xf,0x0,0xc,0x63,0x6c,0x69,0x65,0x6e,0x74,0x5f,0x74,0x65,0x73,0x74,0x31}; 43 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 44 | 45 | shimClient.expect(connect,28); 46 | shimClient.respond(connack,4); 47 | 48 | PubSubClient client(server, 1883, callback, shimClient); 49 | int rc = client.connect((char*)"client_test1"); 50 | IS_TRUE(rc); 51 | IS_FALSE(shimClient.error()); 52 | 53 | END_IT 54 | } 55 | 56 | int test_connect_properly_formatted_hostname() { 57 | IT("accepts a hostname"); 58 | ShimClient shimClient; 59 | 60 | shimClient.setAllowConnect(true); 61 | shimClient.expectConnect((char* const)"localhost",1883); 62 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 63 | shimClient.respond(connack,4); 64 | 65 | PubSubClient client((char* const)"localhost", 1883, callback, shimClient); 66 | int rc = client.connect((char*)"client_test1"); 67 | IS_TRUE(rc); 68 | IS_FALSE(shimClient.error()); 69 | 70 | END_IT 71 | } 72 | 73 | 74 | int test_connect_fails_on_bad_rc() { 75 | IT("fails to connect if a bad return code is received"); 76 | ShimClient shimClient; 77 | shimClient.setAllowConnect(true); 78 | byte connack[] = { 0x20, 0x02, 0x00, 0x01 }; 79 | shimClient.respond(connack,4); 80 | 81 | PubSubClient client(server, 1883, callback, shimClient); 82 | int rc = client.connect((char*)"client_test1"); 83 | IS_FALSE(rc); 84 | END_IT 85 | } 86 | 87 | int test_connect_accepts_username_password() { 88 | IT("accepts a username and password"); 89 | ShimClient shimClient; 90 | shimClient.setAllowConnect(true); 91 | 92 | byte connect[] = { 0x10,0x26,0x0,0x6,0x4d,0x51,0x49,0x73,0x64,0x70,0x3,0xc2,0x0,0xf,0x0,0xc,0x63,0x6c,0x69,0x65,0x6e,0x74,0x5f,0x74,0x65,0x73,0x74,0x31,0x0,0x4,0x75,0x73,0x65,0x72,0x0,0x4,0x70,0x61,0x73,0x73}; 93 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 94 | shimClient.expect(connect,0x28); 95 | shimClient.respond(connack,4); 96 | 97 | PubSubClient client(server, 1883, callback, shimClient); 98 | int rc = client.connect((char*)"client_test1",(char*)"user",(char*)"pass"); 99 | IS_TRUE(rc); 100 | IS_FALSE(shimClient.error()); 101 | 102 | END_IT 103 | } 104 | 105 | int test_connect_accepts_username_no_password() { 106 | IT("accepts a username but no password"); 107 | ShimClient shimClient; 108 | shimClient.setAllowConnect(true); 109 | 110 | byte connect[] = { 0x10,0x20,0x0,0x6,0x4d,0x51,0x49,0x73,0x64,0x70,0x3,0x82,0x0,0xf,0x0,0xc,0x63,0x6c,0x69,0x65,0x6e,0x74,0x5f,0x74,0x65,0x73,0x74,0x31,0x0,0x4,0x75,0x73,0x65,0x72}; 111 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 112 | shimClient.expect(connect,0x22); 113 | shimClient.respond(connack,4); 114 | 115 | PubSubClient client(server, 1883, callback, shimClient); 116 | int rc = client.connect((char*)"client_test1",(char*)"user",'\0'); 117 | IS_TRUE(rc); 118 | IS_FALSE(shimClient.error()); 119 | 120 | END_IT 121 | } 122 | 123 | int test_connect_ignores_password_no_username() { 124 | IT("ignores a password but no username"); 125 | ShimClient shimClient; 126 | shimClient.setAllowConnect(true); 127 | 128 | byte connect[] = {0x10,0x1a,0x0,0x6,0x4d,0x51,0x49,0x73,0x64,0x70,0x3,0x2,0x0,0xf,0x0,0xc,0x63,0x6c,0x69,0x65,0x6e,0x74,0x5f,0x74,0x65,0x73,0x74,0x31}; 129 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 130 | shimClient.expect(connect,28); 131 | shimClient.respond(connack,4); 132 | 133 | PubSubClient client(server, 1883, callback, shimClient); 134 | int rc = client.connect((char*)"client_test1",'\0',(char*)"pass"); 135 | IS_TRUE(rc); 136 | IS_FALSE(shimClient.error()); 137 | 138 | END_IT 139 | } 140 | 141 | int test_connect_with_will() { 142 | IT("accepts a will"); 143 | ShimClient shimClient; 144 | shimClient.setAllowConnect(true); 145 | 146 | byte connect[] = {0x10,0x32,0x0,0x6,0x4d,0x51,0x49,0x73,0x64,0x70,0x3,0xe,0x0,0xf,0x0,0xc,0x63,0x6c,0x69,0x65,0x6e,0x74,0x5f,0x74,0x65,0x73,0x74,0x31,0x0,0x9,0x77,0x69,0x6c,0x6c,0x54,0x6f,0x70,0x69,0x63,0x0,0xb,0x77,0x69,0x6c,0x6c,0x4d,0x65,0x73,0x73,0x61,0x67,0x65}; 147 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 148 | shimClient.expect(connect,0x34); 149 | shimClient.respond(connack,4); 150 | 151 | PubSubClient client(server, 1883, callback, shimClient); 152 | int rc = client.connect((char*)"client_test1",(char*)"willTopic",1,0,(char*)"willMessage"); 153 | IS_TRUE(rc); 154 | IS_FALSE(shimClient.error()); 155 | 156 | END_IT 157 | } 158 | 159 | int test_connect_with_will_username_password() { 160 | IT("accepts a will, username and password"); 161 | ShimClient shimClient; 162 | shimClient.setAllowConnect(true); 163 | 164 | byte connect[] = {0x10,0x42,0x0,0x6,0x4d,0x51,0x49,0x73,0x64,0x70,0x3,0xce,0x0,0xf,0x0,0xc,0x63,0x6c,0x69,0x65,0x6e,0x74,0x5f,0x74,0x65,0x73,0x74,0x31,0x0,0x9,0x77,0x69,0x6c,0x6c,0x54,0x6f,0x70,0x69,0x63,0x0,0xb,0x77,0x69,0x6c,0x6c,0x4d,0x65,0x73,0x73,0x61,0x67,0x65,0x0,0x4,0x75,0x73,0x65,0x72,0x0,0x8,0x70,0x61,0x73,0x73,0x77,0x6f,0x72,0x64}; 165 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 166 | shimClient.expect(connect,0x44); 167 | shimClient.respond(connack,4); 168 | 169 | PubSubClient client(server, 1883, callback, shimClient); 170 | int rc = client.connect((char*)"client_test1",(char*)"user",(char*)"password",(char*)"willTopic",1,0,(char*)"willMessage"); 171 | IS_TRUE(rc); 172 | IS_FALSE(shimClient.error()); 173 | 174 | END_IT 175 | } 176 | 177 | int test_connect_disconnect_connect() { 178 | IT("connects, disconnects and connects again"); 179 | ShimClient shimClient; 180 | 181 | shimClient.setAllowConnect(true); 182 | byte expectServer[] = { 172, 16, 0, 2 }; 183 | shimClient.expectConnect(expectServer,1883); 184 | byte connect[] = {0x10,0x1a,0x0,0x6,0x4d,0x51,0x49,0x73,0x64,0x70,0x3,0x2,0x0,0xf,0x0,0xc,0x63,0x6c,0x69,0x65,0x6e,0x74,0x5f,0x74,0x65,0x73,0x74,0x31}; 185 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 186 | 187 | shimClient.expect(connect,28); 188 | shimClient.respond(connack,4); 189 | 190 | PubSubClient client(server, 1883, callback, shimClient); 191 | int rc = client.connect((char*)"client_test1"); 192 | IS_TRUE(rc); 193 | IS_FALSE(shimClient.error()); 194 | 195 | byte disconnect[] = {0xE0,0x00}; 196 | shimClient.expect(disconnect,2); 197 | 198 | client.disconnect(); 199 | 200 | IS_FALSE(client.connected()); 201 | IS_FALSE(shimClient.connected()); 202 | IS_FALSE(shimClient.error()); 203 | 204 | shimClient.expect(connect,28); 205 | shimClient.respond(connack,4); 206 | rc = client.connect((char*)"client_test1"); 207 | IS_TRUE(rc); 208 | IS_FALSE(shimClient.error()); 209 | 210 | END_IT 211 | } 212 | 213 | int main() 214 | { 215 | test_connect_fails_no_network(); 216 | test_connect_fails_on_no_response(); 217 | test_connect_properly_formatted(); 218 | test_connect_fails_on_bad_rc(); 219 | test_connect_properly_formatted_hostname(); 220 | test_connect_accepts_username_password(); 221 | test_connect_accepts_username_no_password(); 222 | test_connect_ignores_password_no_username(); 223 | test_connect_with_will(); 224 | test_connect_with_will_username_password(); 225 | test_connect_disconnect_connect(); 226 | 227 | FINISH 228 | } 229 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/tests/src/keepalive_spec.cpp: -------------------------------------------------------------------------------- 1 | #include "PubSubClient.h" 2 | #include "ShimClient.h" 3 | #include "Buffer.h" 4 | #include "BDDTest.h" 5 | #include "trace.h" 6 | 7 | 8 | byte server[] = { 172, 16, 0, 2 }; 9 | 10 | void callback(char* topic, byte* payload, unsigned int length) { 11 | // handle message arrived 12 | } 13 | 14 | 15 | int test_keepalive_pings_idle() { 16 | IT("keeps an idle connection alive"); 17 | 18 | ShimClient shimClient; 19 | shimClient.setAllowConnect(true); 20 | 21 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 22 | shimClient.respond(connack,4); 23 | 24 | PubSubClient client(server, 1883, callback, shimClient); 25 | int rc = client.connect((char*)"client_test1"); 26 | IS_TRUE(rc); 27 | 28 | byte pingreq[] = { 0xC0,0x0 }; 29 | shimClient.expect(pingreq,2); 30 | byte pingresp[] = { 0xD0,0x0 }; 31 | shimClient.respond(pingresp,2); 32 | 33 | for (int i = 0; i < 50; i++) { 34 | sleep(1); 35 | rc = client.loop(); 36 | IS_TRUE(rc); 37 | } 38 | 39 | IS_FALSE(shimClient.error()); 40 | 41 | END_IT 42 | } 43 | 44 | int test_keepalive_pings_with_outbound_qos0() { 45 | IT("keeps a connection alive that only sends qos0"); 46 | 47 | ShimClient shimClient; 48 | shimClient.setAllowConnect(true); 49 | 50 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 51 | shimClient.respond(connack,4); 52 | 53 | PubSubClient client(server, 1883, callback, shimClient); 54 | int rc = client.connect((char*)"client_test1"); 55 | IS_TRUE(rc); 56 | 57 | byte publish[] = {0x30,0xe,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64}; 58 | 59 | for (int i = 0; i < 50; i++) { 60 | TRACE(i<<":"); 61 | shimClient.expect(publish,16); 62 | rc = client.publish((char*)"topic",(char*)"payload"); 63 | IS_TRUE(rc); 64 | IS_FALSE(shimClient.error()); 65 | sleep(1); 66 | if ( i == 15 || i == 31 || i == 47) { 67 | byte pingreq[] = { 0xC0,0x0 }; 68 | shimClient.expect(pingreq,2); 69 | byte pingresp[] = { 0xD0,0x0 }; 70 | shimClient.respond(pingresp,2); 71 | } 72 | rc = client.loop(); 73 | IS_TRUE(rc); 74 | IS_FALSE(shimClient.error()); 75 | } 76 | 77 | END_IT 78 | } 79 | 80 | int test_keepalive_pings_with_inbound_qos0() { 81 | IT("keeps a connection alive that only receives qos0"); 82 | 83 | ShimClient shimClient; 84 | shimClient.setAllowConnect(true); 85 | 86 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 87 | shimClient.respond(connack,4); 88 | 89 | PubSubClient client(server, 1883, callback, shimClient); 90 | int rc = client.connect((char*)"client_test1"); 91 | IS_TRUE(rc); 92 | 93 | byte publish[] = {0x30,0xe,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64}; 94 | 95 | for (int i = 0; i < 50; i++) { 96 | TRACE(i<<":"); 97 | sleep(1); 98 | if ( i == 15 || i == 31 || i == 47) { 99 | byte pingreq[] = { 0xC0,0x0 }; 100 | shimClient.expect(pingreq,2); 101 | byte pingresp[] = { 0xD0,0x0 }; 102 | shimClient.respond(pingresp,2); 103 | } 104 | shimClient.respond(publish,16); 105 | rc = client.loop(); 106 | IS_TRUE(rc); 107 | IS_FALSE(shimClient.error()); 108 | } 109 | 110 | END_IT 111 | } 112 | 113 | int test_keepalive_no_pings_inbound_qos1() { 114 | IT("does not send pings for connections with inbound qos1"); 115 | 116 | ShimClient shimClient; 117 | shimClient.setAllowConnect(true); 118 | 119 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 120 | shimClient.respond(connack,4); 121 | 122 | PubSubClient client(server, 1883, callback, shimClient); 123 | int rc = client.connect((char*)"client_test1"); 124 | IS_TRUE(rc); 125 | 126 | byte publish[] = {0x32,0x10,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x12,0x34,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64}; 127 | byte puback[] = {0x40,0x2,0x12,0x34}; 128 | 129 | for (int i = 0; i < 50; i++) { 130 | shimClient.respond(publish,18); 131 | shimClient.expect(puback,4); 132 | sleep(1); 133 | rc = client.loop(); 134 | IS_TRUE(rc); 135 | IS_FALSE(shimClient.error()); 136 | } 137 | 138 | END_IT 139 | } 140 | 141 | int test_keepalive_disconnects_hung() { 142 | IT("disconnects a hung connection"); 143 | 144 | ShimClient shimClient; 145 | shimClient.setAllowConnect(true); 146 | 147 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 148 | shimClient.respond(connack,4); 149 | 150 | PubSubClient client(server, 1883, callback, shimClient); 151 | int rc = client.connect((char*)"client_test1"); 152 | IS_TRUE(rc); 153 | 154 | byte pingreq[] = { 0xC0,0x0 }; 155 | shimClient.expect(pingreq,2); 156 | 157 | for (int i = 0; i < 32; i++) { 158 | sleep(1); 159 | rc = client.loop(); 160 | } 161 | IS_FALSE(rc); 162 | 163 | IS_FALSE(shimClient.error()); 164 | 165 | END_IT 166 | } 167 | 168 | int main() 169 | { 170 | test_keepalive_pings_idle(); 171 | test_keepalive_pings_with_outbound_qos0(); 172 | test_keepalive_pings_with_inbound_qos0(); 173 | test_keepalive_no_pings_inbound_qos1(); 174 | test_keepalive_disconnects_hung(); 175 | 176 | FINISH 177 | } 178 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/tests/src/lib/Arduino.h: -------------------------------------------------------------------------------- 1 | #ifndef Arduino_h 2 | #define Arduino_h 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | extern "C"{ 11 | typedef uint8_t byte ; 12 | typedef uint8_t boolean ; 13 | 14 | /* sketch */ 15 | extern void setup( void ) ; 16 | extern void loop( void ) ; 17 | uint32_t millis( void ); 18 | } 19 | 20 | #define PROGMEM 21 | #define pgm_read_byte_near(x) *(x) 22 | 23 | #endif // Arduino_h 24 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/tests/src/lib/BDDTest.cpp: -------------------------------------------------------------------------------- 1 | #include "BDDTest.h" 2 | #include "trace.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int testCount = 0; 9 | int testPasses = 0; 10 | const char* testDescription; 11 | 12 | std::list failureList; 13 | 14 | int bddtest_test(const char* file, int line, const char* assertion, int result) { 15 | if (!result) { 16 | LOG("F"); 17 | std::ostringstream os; 18 | os << " ! "<::iterator it = failureList.begin(); it != failureList.end(); it++) { 36 | LOG("\n"); 37 | LOG(*it); 38 | } 39 | LOG("\n" << std::dec << testPasses << "/" << testCount << " tests passed\n"); 40 | if (testPasses == testCount) { 41 | return 0; 42 | } 43 | return 1; 44 | } 45 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/tests/src/lib/BDDTest.h: -------------------------------------------------------------------------------- 1 | #ifndef bddtest_h 2 | #define bddtest_h 3 | 4 | int bddtest_test(const char*, int, const char*, int); 5 | void bddtest_start(const char*); 6 | void bddtest_end(); 7 | int bddtest_summary(); 8 | 9 | #define TEST(x) { if (!bddtest_test(__FILE__, __LINE__, #x, (x))) return false; } 10 | 11 | #define IT(x) { bddtest_start(x); } 12 | #define END_IT { bddtest_end();return true;} 13 | 14 | #define FINISH { return bddtest_summary(); } 15 | 16 | #define IS_TRUE(x) TEST(x) 17 | #define IS_FALSE(x) TEST(!(x)) 18 | #define IS_EQUAL(x,y) TEST(x==y) 19 | #define IS_NOT_EQUAL(x,y) TEST(x!=y) 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/tests/src/lib/Buffer.cpp: -------------------------------------------------------------------------------- 1 | #include "Buffer.h" 2 | #include "Arduino.h" 3 | 4 | Buffer::Buffer() { 5 | } 6 | 7 | Buffer::Buffer(uint8_t* buf, size_t size) { 8 | this->add(buf,size); 9 | } 10 | bool Buffer::available() { 11 | return this->pos < this->length; 12 | } 13 | 14 | uint8_t Buffer::next() { 15 | if (this->available()) { 16 | return this->buffer[this->pos++]; 17 | } 18 | return 0; 19 | } 20 | 21 | void Buffer::reset() { 22 | this->pos = 0; 23 | } 24 | 25 | void Buffer::add(uint8_t* buf, size_t size) { 26 | uint16_t i = 0; 27 | for (;ibuffer[this->length++] = buf[i]; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/tests/src/lib/Buffer.h: -------------------------------------------------------------------------------- 1 | #ifndef buffer_h 2 | #define buffer_h 3 | 4 | #include "Arduino.h" 5 | 6 | class Buffer { 7 | private: 8 | uint8_t buffer[1024]; 9 | uint16_t pos; 10 | uint16_t length; 11 | 12 | public: 13 | Buffer(); 14 | Buffer(uint8_t* buf, size_t size); 15 | 16 | virtual bool available(); 17 | virtual uint8_t next(); 18 | virtual void reset(); 19 | 20 | virtual void add(uint8_t* buf, size_t size); 21 | }; 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/tests/src/lib/Client.h: -------------------------------------------------------------------------------- 1 | #ifndef client_h 2 | #define client_h 3 | #include "IPAddress.h" 4 | 5 | class Client { 6 | public: 7 | virtual int connect(IPAddress ip, uint16_t port) =0; 8 | virtual int connect(const char *host, uint16_t port) =0; 9 | virtual size_t write(uint8_t) =0; 10 | virtual size_t write(const uint8_t *buf, size_t size) =0; 11 | virtual int available() = 0; 12 | virtual int read() = 0; 13 | virtual int read(uint8_t *buf, size_t size) = 0; 14 | virtual int peek() = 0; 15 | virtual void flush() = 0; 16 | virtual void stop() = 0; 17 | virtual uint8_t connected() = 0; 18 | virtual operator bool() = 0; 19 | }; 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/tests/src/lib/IPAddress.h: -------------------------------------------------------------------------------- 1 | #ifndef IPAddress_h 2 | #define IPAddress_h 3 | 4 | extern "C" { 5 | 6 | #define IPAddress uint8_t* 7 | 8 | } 9 | 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/tests/src/lib/ShimClient.cpp: -------------------------------------------------------------------------------- 1 | #include "ShimClient.h" 2 | #include "trace.h" 3 | #include 4 | #include 5 | #include 6 | 7 | extern "C" { 8 | uint32_t millis(void) { 9 | return time(0)*1000; 10 | } 11 | } 12 | 13 | ShimClient::ShimClient() { 14 | this->responseBuffer = new Buffer(); 15 | this->expectBuffer = new Buffer(); 16 | this->_allowConnect = true; 17 | this->_connected = false; 18 | this->_error = false; 19 | this->expectAnything = true; 20 | this->_received = 0; 21 | this->_expectedPort = 0; 22 | } 23 | 24 | int ShimClient::connect(IPAddress ip, uint16_t port) { 25 | if (this->_allowConnect) { 26 | this->_connected = true; 27 | } 28 | if (this->_expectedPort !=0) { 29 | if (memcmp(ip,this->_expectedIP,4) != 0) { 30 | TRACE( "ip mismatch\n"); 31 | this->_error = true; 32 | } 33 | if (port != this->_expectedPort) { 34 | TRACE( "port mismatch\n"); 35 | this->_error = true; 36 | } 37 | } 38 | return this->_connected; 39 | } 40 | int ShimClient::connect(const char *host, uint16_t port) { 41 | if (this->_allowConnect) { 42 | this->_connected = true; 43 | } 44 | if (this->_expectedPort !=0) { 45 | if (strcmp(host,this->_expectedHost) != 0) { 46 | TRACE( "host mismatch\n"); 47 | this->_error = true; 48 | } 49 | if (port != this->_expectedPort) { 50 | TRACE( "port mismatch\n"); 51 | this->_error = true; 52 | } 53 | 54 | } 55 | return this->_connected; 56 | } 57 | size_t ShimClient::write(uint8_t b) { 58 | this->_received += 1; 59 | TRACE(std::hex << (unsigned int)b); 60 | if (!this->expectAnything) { 61 | if (this->expectBuffer->available()) { 62 | uint8_t expected = this->expectBuffer->next(); 63 | if (expected != b) { 64 | this->_error = true; 65 | TRACE("!=" << (unsigned int)expected); 66 | } 67 | } else { 68 | this->_error = true; 69 | } 70 | } 71 | TRACE("\n"<< std::dec); 72 | return 1; 73 | } 74 | size_t ShimClient::write(const uint8_t *buf, size_t size) { 75 | this->_received += size; 76 | TRACE( "[" << std::dec << (unsigned int)(size) << "] "); 77 | uint16_t i=0; 78 | for (;i0) { 80 | TRACE(":"); 81 | } 82 | TRACE(std::hex << (unsigned int)(buf[i])); 83 | 84 | if (!this->expectAnything) { 85 | if (this->expectBuffer->available()) { 86 | uint8_t expected = this->expectBuffer->next(); 87 | if (expected != buf[i]) { 88 | this->_error = true; 89 | TRACE("!=" << (unsigned int)expected); 90 | } 91 | } else { 92 | this->_error = true; 93 | } 94 | } 95 | } 96 | TRACE("\n"<responseBuffer->available(); 101 | } 102 | int ShimClient::read() { return this->responseBuffer->next(); } 103 | int ShimClient::read(uint8_t *buf, size_t size) { 104 | uint16_t i = 0; 105 | for (;iread(); 107 | } 108 | return size; 109 | } 110 | int ShimClient::peek() { return 0; } 111 | void ShimClient::flush() {} 112 | void ShimClient::stop() { 113 | this->setConnected(false); 114 | } 115 | uint8_t ShimClient::connected() { return this->_connected; } 116 | ShimClient::operator bool() { return true; } 117 | 118 | 119 | ShimClient* ShimClient::respond(uint8_t *buf, size_t size) { 120 | this->responseBuffer->add(buf,size); 121 | return this; 122 | } 123 | 124 | ShimClient* ShimClient::expect(uint8_t *buf, size_t size) { 125 | this->expectAnything = false; 126 | this->expectBuffer->add(buf,size); 127 | return this; 128 | } 129 | 130 | void ShimClient::setConnected(bool b) { 131 | this->_connected = b; 132 | } 133 | void ShimClient::setAllowConnect(bool b) { 134 | this->_allowConnect = b; 135 | } 136 | 137 | bool ShimClient::error() { 138 | return this->_error; 139 | } 140 | 141 | uint16_t ShimClient::received() { 142 | return this->_received; 143 | } 144 | 145 | void ShimClient::expectConnect(IPAddress ip, uint16_t port) { 146 | this->_expectedIP = ip; 147 | this->_expectedPort = port; 148 | } 149 | 150 | void ShimClient::expectConnect(const char *host, uint16_t port) { 151 | this->_expectedHost = host; 152 | this->_expectedPort = port; 153 | } 154 | 155 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/tests/src/lib/ShimClient.h: -------------------------------------------------------------------------------- 1 | #ifndef shimclient_h 2 | #define shimclient_h 3 | 4 | #include "Arduino.h" 5 | #include "Client.h" 6 | #include "IPAddress.h" 7 | #include "Buffer.h" 8 | 9 | 10 | class ShimClient : public Client { 11 | private: 12 | Buffer* responseBuffer; 13 | Buffer* expectBuffer; 14 | bool _allowConnect; 15 | bool _connected; 16 | bool expectAnything; 17 | bool _error; 18 | uint16_t _received; 19 | IPAddress _expectedIP; 20 | uint16_t _expectedPort; 21 | const char* _expectedHost; 22 | 23 | public: 24 | ShimClient(); 25 | virtual int connect(IPAddress ip, uint16_t port); 26 | virtual int connect(const char *host, uint16_t port); 27 | virtual size_t write(uint8_t); 28 | virtual size_t write(const uint8_t *buf, size_t size); 29 | virtual int available(); 30 | virtual int read(); 31 | virtual int read(uint8_t *buf, size_t size); 32 | virtual int peek(); 33 | virtual void flush(); 34 | virtual void stop(); 35 | virtual uint8_t connected(); 36 | virtual operator bool(); 37 | 38 | virtual ShimClient* respond(uint8_t *buf, size_t size); 39 | virtual ShimClient* expect(uint8_t *buf, size_t size); 40 | 41 | virtual void expectConnect(IPAddress ip, uint16_t port); 42 | virtual void expectConnect(const char *host, uint16_t port); 43 | 44 | virtual uint16_t received(); 45 | virtual bool error(); 46 | 47 | virtual void setAllowConnect(bool b); 48 | virtual void setConnected(bool b); 49 | }; 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/tests/src/lib/Stream.cpp: -------------------------------------------------------------------------------- 1 | #include "Stream.h" 2 | #include "trace.h" 3 | #include 4 | #include 5 | 6 | Stream::Stream() { 7 | this->expectBuffer = new Buffer(); 8 | this->_error = false; 9 | this->_written = 0; 10 | } 11 | 12 | size_t Stream::write(uint8_t b) { 13 | this->_written++; 14 | TRACE(std::hex << (unsigned int)b); 15 | if (this->expectBuffer->available()) { 16 | uint8_t expected = this->expectBuffer->next(); 17 | if (expected != b) { 18 | this->_error = true; 19 | TRACE("!=" << (unsigned int)expected); 20 | } 21 | } else { 22 | this->_error = true; 23 | } 24 | TRACE("\n"<< std::dec); 25 | return 1; 26 | } 27 | 28 | 29 | bool Stream::error() { 30 | return this->_error; 31 | } 32 | 33 | void Stream::expect(uint8_t *buf, size_t size) { 34 | this->expectBuffer->add(buf,size); 35 | } 36 | 37 | uint16_t Stream::length() { 38 | return this->_written; 39 | } 40 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/tests/src/lib/Stream.h: -------------------------------------------------------------------------------- 1 | #ifndef Stream_h 2 | #define Stream_h 3 | 4 | #include "Arduino.h" 5 | #include "Buffer.h" 6 | 7 | class Stream { 8 | private: 9 | Buffer* expectBuffer; 10 | bool _error; 11 | uint16_t _written; 12 | 13 | public: 14 | Stream(); 15 | virtual size_t write(uint8_t); 16 | 17 | virtual bool error(); 18 | virtual void expect(uint8_t *buf, size_t size); 19 | virtual uint16_t length(); 20 | }; 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/tests/src/lib/trace.h: -------------------------------------------------------------------------------- 1 | #ifndef trace_h 2 | #define trace_h 3 | #include 4 | 5 | #include 6 | 7 | #define LOG(x) {std::cout << x << std::flush; } 8 | #define TRACE(x) {if (getenv("TRACE")) { std::cout << x << std::flush; }} 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/tests/src/publish_spec.cpp: -------------------------------------------------------------------------------- 1 | #include "PubSubClient.h" 2 | #include "ShimClient.h" 3 | #include "Buffer.h" 4 | #include "BDDTest.h" 5 | #include "trace.h" 6 | 7 | 8 | byte server[] = { 172, 16, 0, 2 }; 9 | 10 | void callback(char* topic, byte* payload, unsigned int length) { 11 | // handle message arrived 12 | } 13 | 14 | int test_publish() { 15 | IT("publishes a null-terminated string"); 16 | ShimClient shimClient; 17 | shimClient.setAllowConnect(true); 18 | 19 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 20 | shimClient.respond(connack,4); 21 | 22 | PubSubClient client(server, 1883, callback, shimClient); 23 | int rc = client.connect((char*)"client_test1"); 24 | IS_TRUE(rc); 25 | 26 | byte publish[] = {0x30,0xe,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64}; 27 | shimClient.expect(publish,16); 28 | 29 | rc = client.publish((char*)"topic",(char*)"payload"); 30 | IS_TRUE(rc); 31 | 32 | IS_FALSE(shimClient.error()); 33 | 34 | END_IT 35 | } 36 | 37 | 38 | int test_publish_bytes() { 39 | IT("publishes a byte array"); 40 | ShimClient shimClient; 41 | shimClient.setAllowConnect(true); 42 | 43 | byte payload[] = { 0x01,0x02,0x03,0x0,0x05 }; 44 | int length = 5; 45 | 46 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 47 | shimClient.respond(connack,4); 48 | 49 | PubSubClient client(server, 1883, callback, shimClient); 50 | int rc = client.connect((char*)"client_test1"); 51 | IS_TRUE(rc); 52 | 53 | byte publish[] = {0x30,0xc,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x1,0x2,0x3,0x0,0x5}; 54 | shimClient.expect(publish,14); 55 | 56 | rc = client.publish((char*)"topic",payload,length); 57 | IS_TRUE(rc); 58 | 59 | IS_FALSE(shimClient.error()); 60 | 61 | END_IT 62 | } 63 | 64 | 65 | int test_publish_retained() { 66 | IT("publishes retained"); 67 | ShimClient shimClient; 68 | shimClient.setAllowConnect(true); 69 | 70 | byte payload[] = { 0x01,0x02,0x03,0x0,0x05 }; 71 | int length = 5; 72 | 73 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 74 | shimClient.respond(connack,4); 75 | 76 | PubSubClient client(server, 1883, callback, shimClient); 77 | int rc = client.connect((char*)"client_test1"); 78 | IS_TRUE(rc); 79 | 80 | byte publish[] = {0x31,0xc,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x1,0x2,0x3,0x0,0x5}; 81 | shimClient.expect(publish,14); 82 | 83 | rc = client.publish((char*)"topic",payload,length,true); 84 | IS_TRUE(rc); 85 | 86 | IS_FALSE(shimClient.error()); 87 | 88 | END_IT 89 | } 90 | 91 | int test_publish_not_connected() { 92 | IT("publish fails when not connected"); 93 | ShimClient shimClient; 94 | 95 | PubSubClient client(server, 1883, callback, shimClient); 96 | 97 | int rc = client.publish((char*)"topic",(char*)"payload"); 98 | IS_FALSE(rc); 99 | 100 | IS_FALSE(shimClient.error()); 101 | 102 | END_IT 103 | } 104 | 105 | 106 | int test_publish_P() { 107 | IT("publishes using PROGMEM"); 108 | ShimClient shimClient; 109 | shimClient.setAllowConnect(true); 110 | 111 | byte payload[] = { 0x01,0x02,0x03,0x0,0x05 }; 112 | int length = 5; 113 | 114 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 115 | shimClient.respond(connack,4); 116 | 117 | PubSubClient client(server, 1883, callback, shimClient); 118 | int rc = client.connect((char*)"client_test1"); 119 | IS_TRUE(rc); 120 | 121 | byte publish[] = {0x31,0xc,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x1,0x2,0x3,0x0,0x5}; 122 | shimClient.expect(publish,14); 123 | 124 | rc = client.publish_P((char*)"topic",payload,length,true); 125 | IS_TRUE(rc); 126 | 127 | IS_FALSE(shimClient.error()); 128 | 129 | END_IT 130 | } 131 | 132 | 133 | int main() 134 | { 135 | test_publish(); 136 | test_publish_bytes(); 137 | test_publish_retained(); 138 | test_publish_not_connected(); 139 | test_publish_P(); 140 | 141 | FINISH 142 | } 143 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/tests/src/receive_spec.cpp: -------------------------------------------------------------------------------- 1 | #include "PubSubClient.h" 2 | #include "ShimClient.h" 3 | #include "Buffer.h" 4 | #include "BDDTest.h" 5 | #include "trace.h" 6 | 7 | 8 | byte server[] = { 172, 16, 0, 2 }; 9 | 10 | bool callback_called = false; 11 | char lastTopic[1024]; 12 | char lastPayload[1024]; 13 | unsigned int lastLength; 14 | 15 | void reset_callback() { 16 | callback_called = false; 17 | lastTopic[0] = '\0'; 18 | lastPayload[0] = '\0'; 19 | lastLength = 0; 20 | } 21 | 22 | void callback(char* topic, byte* payload, unsigned int length) { 23 | callback_called = true; 24 | strcpy(lastTopic,topic); 25 | memcpy(lastPayload,payload,length); 26 | lastLength = length; 27 | } 28 | 29 | int test_receive_callback() { 30 | IT("receives a callback message"); 31 | reset_callback(); 32 | 33 | ShimClient shimClient; 34 | shimClient.setAllowConnect(true); 35 | 36 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 37 | shimClient.respond(connack,4); 38 | 39 | PubSubClient client(server, 1883, callback, shimClient); 40 | int rc = client.connect((char*)"client_test1"); 41 | IS_TRUE(rc); 42 | 43 | byte publish[] = {0x30,0xe,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64}; 44 | shimClient.respond(publish,16); 45 | 46 | rc = client.loop(); 47 | 48 | IS_TRUE(rc); 49 | 50 | IS_TRUE(callback_called); 51 | IS_TRUE(strcmp(lastTopic,"topic")==0); 52 | IS_TRUE(memcmp(lastPayload,"payload",7)==0); 53 | IS_TRUE(lastLength == 7); 54 | 55 | IS_FALSE(shimClient.error()); 56 | 57 | END_IT 58 | } 59 | 60 | int test_receive_stream() { 61 | IT("receives a streamed callback message"); 62 | reset_callback(); 63 | 64 | Stream stream; 65 | stream.expect((uint8_t*)"payload",7); 66 | 67 | ShimClient shimClient; 68 | shimClient.setAllowConnect(true); 69 | 70 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 71 | shimClient.respond(connack,4); 72 | 73 | PubSubClient client(server, 1883, callback, shimClient, stream); 74 | int rc = client.connect((char*)"client_test1"); 75 | IS_TRUE(rc); 76 | 77 | byte publish[] = {0x30,0xe,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64}; 78 | shimClient.respond(publish,16); 79 | 80 | rc = client.loop(); 81 | 82 | IS_TRUE(rc); 83 | 84 | IS_TRUE(callback_called); 85 | IS_TRUE(strcmp(lastTopic,"topic")==0); 86 | IS_TRUE(lastLength == 7); 87 | 88 | IS_FALSE(stream.error()); 89 | IS_FALSE(shimClient.error()); 90 | 91 | END_IT 92 | } 93 | 94 | int test_receive_max_sized_message() { 95 | IT("receives an max-sized message"); 96 | reset_callback(); 97 | 98 | ShimClient shimClient; 99 | shimClient.setAllowConnect(true); 100 | 101 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 102 | shimClient.respond(connack,4); 103 | 104 | PubSubClient client(server, 1883, callback, shimClient); 105 | int rc = client.connect((char*)"client_test1"); 106 | IS_TRUE(rc); 107 | 108 | byte length = MQTT_MAX_PACKET_SIZE; 109 | byte publish[] = {0x30,length-2,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64}; 110 | byte bigPublish[length]; 111 | memset(bigPublish,'A',length); 112 | bigPublish[length] = 'B'; 113 | memcpy(bigPublish,publish,16); 114 | shimClient.respond(bigPublish,length); 115 | 116 | rc = client.loop(); 117 | 118 | IS_TRUE(rc); 119 | 120 | IS_TRUE(callback_called); 121 | IS_TRUE(strcmp(lastTopic,"topic")==0); 122 | IS_TRUE(lastLength == length-9); 123 | IS_TRUE(memcmp(lastPayload,bigPublish+9,lastLength)==0); 124 | 125 | IS_FALSE(shimClient.error()); 126 | 127 | END_IT 128 | } 129 | 130 | int test_receive_oversized_message() { 131 | IT("drops an oversized message"); 132 | reset_callback(); 133 | 134 | ShimClient shimClient; 135 | shimClient.setAllowConnect(true); 136 | 137 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 138 | shimClient.respond(connack,4); 139 | 140 | PubSubClient client(server, 1883, callback, shimClient); 141 | int rc = client.connect((char*)"client_test1"); 142 | IS_TRUE(rc); 143 | 144 | byte length = MQTT_MAX_PACKET_SIZE+1; 145 | byte publish[] = {0x30,length-2,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64}; 146 | byte bigPublish[length]; 147 | memset(bigPublish,'A',length); 148 | bigPublish[length] = 'B'; 149 | memcpy(bigPublish,publish,16); 150 | shimClient.respond(bigPublish,length); 151 | 152 | rc = client.loop(); 153 | 154 | IS_TRUE(rc); 155 | 156 | IS_FALSE(callback_called); 157 | 158 | IS_FALSE(shimClient.error()); 159 | 160 | END_IT 161 | } 162 | 163 | int test_receive_oversized_stream_message() { 164 | IT("drops an oversized message"); 165 | reset_callback(); 166 | 167 | Stream stream; 168 | 169 | ShimClient shimClient; 170 | shimClient.setAllowConnect(true); 171 | 172 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 173 | shimClient.respond(connack,4); 174 | 175 | PubSubClient client(server, 1883, callback, shimClient, stream); 176 | int rc = client.connect((char*)"client_test1"); 177 | IS_TRUE(rc); 178 | 179 | byte length = MQTT_MAX_PACKET_SIZE+1; 180 | byte publish[] = {0x30,length-2,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64}; 181 | 182 | byte bigPublish[length]; 183 | memset(bigPublish,'A',length); 184 | bigPublish[length] = 'B'; 185 | memcpy(bigPublish,publish,16); 186 | 187 | shimClient.respond(bigPublish,length); 188 | stream.expect(bigPublish+9,length-9); 189 | 190 | rc = client.loop(); 191 | 192 | IS_TRUE(rc); 193 | 194 | IS_TRUE(callback_called); 195 | IS_TRUE(strcmp(lastTopic,"topic")==0); 196 | IS_TRUE(lastLength == length-9); 197 | 198 | IS_FALSE(stream.error()); 199 | IS_FALSE(shimClient.error()); 200 | 201 | END_IT 202 | } 203 | 204 | int test_receive_qos1() { 205 | IT("receives a qos1 message"); 206 | reset_callback(); 207 | 208 | ShimClient shimClient; 209 | shimClient.setAllowConnect(true); 210 | 211 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 212 | shimClient.respond(connack,4); 213 | 214 | PubSubClient client(server, 1883, callback, shimClient); 215 | int rc = client.connect((char*)"client_test1"); 216 | IS_TRUE(rc); 217 | 218 | byte publish[] = {0x32,0x10,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x12,0x34,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64}; 219 | shimClient.respond(publish,18); 220 | 221 | byte puback[] = {0x40,0x2,0x12,0x34}; 222 | shimClient.expect(puback,4); 223 | 224 | rc = client.loop(); 225 | 226 | IS_TRUE(rc); 227 | 228 | IS_TRUE(callback_called); 229 | IS_TRUE(strcmp(lastTopic,"topic")==0); 230 | IS_TRUE(memcmp(lastPayload,"payload",7)==0); 231 | IS_TRUE(lastLength == 7); 232 | 233 | IS_FALSE(shimClient.error()); 234 | 235 | END_IT 236 | } 237 | 238 | int main() 239 | { 240 | test_receive_callback(); 241 | test_receive_stream(); 242 | test_receive_max_sized_message(); 243 | test_receive_oversized_message(); 244 | test_receive_oversized_stream_message(); 245 | test_receive_qos1(); 246 | 247 | FINISH 248 | } 249 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/tests/src/subscribe_spec.cpp: -------------------------------------------------------------------------------- 1 | #include "PubSubClient.h" 2 | #include "ShimClient.h" 3 | #include "Buffer.h" 4 | #include "BDDTest.h" 5 | #include "trace.h" 6 | 7 | 8 | byte server[] = { 172, 16, 0, 2 }; 9 | 10 | void callback(char* topic, byte* payload, unsigned int length) { 11 | // handle message arrived 12 | } 13 | 14 | 15 | 16 | int test_subscribe_no_qos() { 17 | IT("subscribe without qos defaults to 0"); 18 | ShimClient shimClient; 19 | shimClient.setAllowConnect(true); 20 | 21 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 22 | shimClient.respond(connack,4); 23 | 24 | PubSubClient client(server, 1883, callback, shimClient); 25 | int rc = client.connect((char*)"client_test1"); 26 | IS_TRUE(rc); 27 | 28 | byte subscribe[] = { 0x82,0xa,0x0,0x2,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x0 }; 29 | shimClient.expect(subscribe,12); 30 | byte suback[] = { 0x90,0x3,0x0,0x2,0x0 }; 31 | shimClient.respond(suback,5); 32 | 33 | rc = client.subscribe((char*)"topic"); 34 | IS_TRUE(rc); 35 | 36 | IS_FALSE(shimClient.error()); 37 | 38 | END_IT 39 | } 40 | 41 | int test_subscribe_qos_1() { 42 | IT("subscribes qos 1"); 43 | ShimClient shimClient; 44 | shimClient.setAllowConnect(true); 45 | 46 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 47 | shimClient.respond(connack,4); 48 | 49 | PubSubClient client(server, 1883, callback, shimClient); 50 | int rc = client.connect((char*)"client_test1"); 51 | IS_TRUE(rc); 52 | 53 | byte subscribe[] = { 0x82,0xa,0x0,0x2,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x1 }; 54 | shimClient.expect(subscribe,12); 55 | byte suback[] = { 0x90,0x3,0x0,0x2,0x1 }; 56 | shimClient.respond(suback,5); 57 | 58 | rc = client.subscribe((char*)"topic",1); 59 | IS_TRUE(rc); 60 | 61 | IS_FALSE(shimClient.error()); 62 | 63 | END_IT 64 | } 65 | 66 | int test_subscribe_not_connected() { 67 | IT("subscribe fails when not connected"); 68 | ShimClient shimClient; 69 | 70 | PubSubClient client(server, 1883, callback, shimClient); 71 | 72 | int rc = client.subscribe((char*)"topic"); 73 | IS_FALSE(rc); 74 | 75 | IS_FALSE(shimClient.error()); 76 | 77 | END_IT 78 | } 79 | 80 | int test_subscribe_invalid_qos() { 81 | IT("subscribe fails when not connected"); 82 | ShimClient shimClient; 83 | shimClient.setAllowConnect(true); 84 | 85 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 86 | shimClient.respond(connack,4); 87 | 88 | PubSubClient client(server, 1883, callback, shimClient); 89 | int rc = client.connect((char*)"client_test1"); 90 | IS_TRUE(rc); 91 | 92 | rc = client.subscribe((char*)"topic",2); 93 | IS_FALSE(rc); 94 | rc = client.subscribe((char*)"topic",254); 95 | IS_FALSE(rc); 96 | 97 | IS_FALSE(shimClient.error()); 98 | 99 | END_IT 100 | } 101 | 102 | int test_unsubscribe() { 103 | IT("unsubscribes"); 104 | ShimClient shimClient; 105 | shimClient.setAllowConnect(true); 106 | 107 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 108 | shimClient.respond(connack,4); 109 | 110 | PubSubClient client(server, 1883, callback, shimClient); 111 | int rc = client.connect((char*)"client_test1"); 112 | IS_TRUE(rc); 113 | 114 | byte unsubscribe[] = { 0xA2,0x9,0x0,0x2,0x0,0x5,0x74,0x6f,0x70,0x69,0x63 }; 115 | shimClient.expect(unsubscribe,12); 116 | byte unsuback[] = { 0xB0,0x2,0x0,0x2 }; 117 | shimClient.respond(unsuback,4); 118 | 119 | rc = client.unsubscribe((char*)"topic"); 120 | IS_TRUE(rc); 121 | 122 | IS_FALSE(shimClient.error()); 123 | 124 | END_IT 125 | } 126 | 127 | int test_unsubscribe_not_connected() { 128 | IT("unsubscribe fails when not connected"); 129 | ShimClient shimClient; 130 | 131 | PubSubClient client(server, 1883, callback, shimClient); 132 | 133 | int rc = client.unsubscribe((char*)"topic"); 134 | IS_FALSE(rc); 135 | 136 | IS_FALSE(shimClient.error()); 137 | 138 | END_IT 139 | } 140 | 141 | int main() 142 | { 143 | test_subscribe_no_qos(); 144 | test_subscribe_qos_1(); 145 | test_subscribe_not_connected(); 146 | test_subscribe_invalid_qos(); 147 | test_unsubscribe(); 148 | test_unsubscribe_not_connected(); 149 | FINISH 150 | } 151 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/tests/testcases/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xDWart/Domophone/725107507ecad677b6d9c493ca5921e75af19886/lib/pubsubclient-master/tests/testcases/__init__.py -------------------------------------------------------------------------------- /lib/pubsubclient-master/tests/testcases/mqtt_basic.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import settings 3 | 4 | import time 5 | import mosquitto 6 | 7 | import serial 8 | 9 | def on_message(mosq, obj, msg): 10 | obj.message_queue.append(msg) 11 | 12 | class mqtt_basic(unittest.TestCase): 13 | 14 | message_queue = [] 15 | 16 | @classmethod 17 | def setUpClass(self): 18 | self.client = mosquitto.Mosquitto("pubsubclient_ut", clean_session=True,obj=self) 19 | self.client.connect(settings.server_ip) 20 | self.client.on_message = on_message 21 | self.client.subscribe("outTopic",0) 22 | 23 | @classmethod 24 | def tearDownClass(self): 25 | self.client.disconnect() 26 | 27 | def test_one(self): 28 | i=30 29 | while len(self.message_queue) == 0 and i > 0: 30 | self.client.loop() 31 | time.sleep(0.5) 32 | i -= 1 33 | self.assertTrue(i>0, "message receive timed-out") 34 | self.assertEqual(len(self.message_queue), 1, "unexpected number of messages received") 35 | msg = self.message_queue[0] 36 | self.assertEqual(msg.mid,0,"message id not 0") 37 | self.assertEqual(msg.topic,"outTopic","message topic incorrect") 38 | self.assertEqual(msg.payload,"hello world") 39 | self.assertEqual(msg.qos,0,"message qos not 0") 40 | self.assertEqual(msg.retain,False,"message retain flag incorrect") 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/tests/testcases/mqtt_publish_in_callback.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import settings 3 | 4 | import time 5 | import mosquitto 6 | 7 | import serial 8 | 9 | def on_message(mosq, obj, msg): 10 | obj.message_queue.append(msg) 11 | 12 | class mqtt_publish_in_callback(unittest.TestCase): 13 | 14 | message_queue = [] 15 | 16 | @classmethod 17 | def setUpClass(self): 18 | self.client = mosquitto.Mosquitto("pubsubclient_ut", clean_session=True,obj=self) 19 | self.client.connect(settings.server_ip) 20 | self.client.on_message = on_message 21 | self.client.subscribe("outTopic",0) 22 | 23 | @classmethod 24 | def tearDownClass(self): 25 | self.client.disconnect() 26 | 27 | def test_connect(self): 28 | i=30 29 | while len(self.message_queue) == 0 and i > 0: 30 | self.client.loop() 31 | time.sleep(0.5) 32 | i -= 1 33 | self.assertTrue(i>0, "message receive timed-out") 34 | self.assertEqual(len(self.message_queue), 1, "unexpected number of messages received") 35 | msg = self.message_queue.pop(0) 36 | self.assertEqual(msg.mid,0,"message id not 0") 37 | self.assertEqual(msg.topic,"outTopic","message topic incorrect") 38 | self.assertEqual(msg.payload,"hello world") 39 | self.assertEqual(msg.qos,0,"message qos not 0") 40 | self.assertEqual(msg.retain,False,"message retain flag incorrect") 41 | 42 | 43 | def test_publish(self): 44 | self.assertEqual(len(self.message_queue), 0, "message queue not empty") 45 | payload = "abcdefghij" 46 | self.client.publish("inTopic",payload) 47 | 48 | i=30 49 | while len(self.message_queue) == 0 and i > 0: 50 | self.client.loop() 51 | time.sleep(0.5) 52 | i -= 1 53 | 54 | self.assertTrue(i>0, "message receive timed-out") 55 | self.assertEqual(len(self.message_queue), 1, "unexpected number of messages received") 56 | msg = self.message_queue.pop(0) 57 | self.assertEqual(msg.mid,0,"message id not 0") 58 | self.assertEqual(msg.topic,"outTopic","message topic incorrect") 59 | self.assertEqual(msg.payload,payload) 60 | self.assertEqual(msg.qos,0,"message qos not 0") 61 | self.assertEqual(msg.retain,False,"message retain flag incorrect") 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/tests/testcases/settings.py: -------------------------------------------------------------------------------- 1 | server_ip = "172.16.0.2" 2 | arduino_ip = "172.16.0.100" 3 | -------------------------------------------------------------------------------- /lib/pubsubclient-master/tests/testsuite.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import os.path 4 | import sys 5 | import shutil 6 | from subprocess import call 7 | import importlib 8 | import unittest 9 | import re 10 | 11 | from testcases import settings 12 | 13 | class Workspace(object): 14 | 15 | def __init__(self): 16 | self.root_dir = os.getcwd() 17 | self.build_dir = os.path.join(self.root_dir,"tmpbin"); 18 | self.log_dir = os.path.join(self.root_dir,"logs"); 19 | self.tests_dir = os.path.join(self.root_dir,"testcases"); 20 | self.examples_dir = os.path.join(self.root_dir,"../PubSubClient/examples") 21 | self.examples = [] 22 | self.tests = [] 23 | if not os.path.isdir("../PubSubClient"): 24 | raise Exception("Cannot find PubSubClient library") 25 | try: 26 | import ino 27 | except: 28 | raise Exception("ino tool not installed") 29 | 30 | def init(self): 31 | if os.path.isdir(self.build_dir): 32 | shutil.rmtree(self.build_dir) 33 | os.mkdir(self.build_dir) 34 | if os.path.isdir(self.log_dir): 35 | shutil.rmtree(self.log_dir) 36 | os.mkdir(self.log_dir) 37 | 38 | os.chdir(self.build_dir) 39 | call(["ino","init"]) 40 | 41 | shutil.copytree("../../PubSubClient","lib/PubSubClient") 42 | 43 | filenames = [] 44 | for root, dirs, files in os.walk(self.examples_dir): 45 | filenames += [os.path.join(root,f) for f in files if f.endswith(".ino")] 46 | filenames.sort() 47 | for e in filenames: 48 | self.examples.append(Sketch(self,e)) 49 | 50 | filenames = [] 51 | for root, dirs, files in os.walk(self.tests_dir): 52 | filenames += [os.path.join(root,f) for f in files if f.endswith(".ino")] 53 | filenames.sort() 54 | for e in filenames: 55 | self.tests.append(Sketch(self,e)) 56 | 57 | def clean(self): 58 | shutil.rmtree(self.build_dir) 59 | 60 | class Sketch(object): 61 | def __init__(self,wksp,fn): 62 | self.w = wksp 63 | self.filename = fn 64 | self.basename = os.path.basename(self.filename) 65 | self.build_log = os.path.join(self.w.log_dir,"%s.log"%(os.path.basename(self.filename),)) 66 | self.build_err_log = os.path.join(self.w.log_dir,"%s.err.log"%(os.path.basename(self.filename),)) 67 | self.build_upload_log = os.path.join(self.w.log_dir,"%s.upload.log"%(os.path.basename(self.filename),)) 68 | 69 | def build(self): 70 | sys.stdout.write(" Build: ") 71 | sys.stdout.flush() 72 | 73 | # Copy sketch over, replacing IP addresses as necessary 74 | fin = open(self.filename,"r") 75 | lines = fin.readlines() 76 | fin.close() 77 | fout = open(os.path.join(self.w.build_dir,"src","sketch.ino"),"w") 78 | for l in lines: 79 | if re.match(r"^byte server\[\] = {",l): 80 | fout.write("byte server[] = { %s };\n"%(settings.server_ip.replace(".",", "),)) 81 | elif re.match(r"^byte ip\[\] = {",l): 82 | fout.write("byte ip[] = { %s };\n"%(settings.arduino_ip.replace(".",", "),)) 83 | else: 84 | fout.write(l) 85 | fout.flush() 86 | fout.close() 87 | 88 | # Run build 89 | fout = open(self.build_log, "w") 90 | ferr = open(self.build_err_log, "w") 91 | rc = call(["ino","build"],stdout=fout,stderr=ferr) 92 | fout.close() 93 | ferr.close() 94 | if rc == 0: 95 | sys.stdout.write("pass") 96 | sys.stdout.write("\n") 97 | return True 98 | else: 99 | sys.stdout.write("fail") 100 | sys.stdout.write("\n") 101 | with open(self.build_err_log) as f: 102 | for line in f: 103 | print " ",line, 104 | return False 105 | 106 | def upload(self): 107 | sys.stdout.write(" Upload: ") 108 | sys.stdout.flush() 109 | fout = open(self.build_upload_log, "w") 110 | rc = call(["ino","upload"],stdout=fout,stderr=fout) 111 | fout.close() 112 | if rc == 0: 113 | sys.stdout.write("pass") 114 | sys.stdout.write("\n") 115 | return True 116 | else: 117 | sys.stdout.write("fail") 118 | sys.stdout.write("\n") 119 | with open(self.build_upload_log) as f: 120 | for line in f: 121 | print " ",line, 122 | return False 123 | 124 | 125 | def test(self): 126 | # import the matching test case, if it exists 127 | try: 128 | basename = os.path.basename(self.filename)[:-4] 129 | i = importlib.import_module("testcases."+basename) 130 | except: 131 | sys.stdout.write(" Test: no tests found") 132 | sys.stdout.write("\n") 133 | return 134 | c = getattr(i,basename) 135 | 136 | testmethods = [m for m in dir(c) if m.startswith("test_")] 137 | testmethods.sort() 138 | tests = [] 139 | for m in testmethods: 140 | tests.append(c(m)) 141 | 142 | result = unittest.TestResult() 143 | c.setUpClass() 144 | if self.upload(): 145 | sys.stdout.write(" Test: ") 146 | sys.stdout.flush() 147 | for t in tests: 148 | t.run(result) 149 | print "%d/%d"%(result.testsRun-len(result.failures)-len(result.errors),result.testsRun) 150 | if not result.wasSuccessful(): 151 | if len(result.failures) > 0: 152 | for f in result.failures: 153 | print "-- %s"%(str(f[0]),) 154 | print f[1] 155 | if len(result.errors) > 0: 156 | print " Errors:" 157 | for f in result.errors: 158 | print "-- %s"%(str(f[0]),) 159 | print f[1] 160 | c.tearDownClass() 161 | 162 | if __name__ == '__main__': 163 | run_tests = True 164 | 165 | w = Workspace() 166 | w.init() 167 | 168 | for e in w.examples: 169 | print "--------------------------------------" 170 | print "[%s]"%(e.basename,) 171 | if e.build() and run_tests: 172 | e.test() 173 | for e in w.tests: 174 | print "--------------------------------------" 175 | print "[%s]"%(e.basename,) 176 | if e.build() and run_tests: 177 | e.test() 178 | 179 | w.clean() 180 | -------------------------------------------------------------------------------- /lib/readme.txt: -------------------------------------------------------------------------------- 1 | 2 | This directory is intended for the project specific (private) libraries. 3 | PlatformIO will compile them to static libraries and link to executable file. 4 | 5 | The source code of each library should be placed in separate directory, like 6 | "lib/private_lib/[here are source files]". 7 | 8 | For example, see how can be organized `Foo` and `Bar` libraries: 9 | 10 | |--lib 11 | | |--Bar 12 | | | |--docs 13 | | | |--examples 14 | | | |--src 15 | | | |- Bar.c 16 | | | |- Bar.h 17 | | |--Foo 18 | | | |- Foo.c 19 | | | |- Foo.h 20 | | |- readme.txt --> THIS FILE 21 | |- platformio.ini 22 | |--src 23 | |- main.c 24 | 25 | Then in `src/main.c` you should use: 26 | 27 | #include 28 | #include 29 | 30 | // rest H/C/CPP code 31 | 32 | PlatformIO will find your libraries automatically, configure preprocessor's 33 | include paths and build them. 34 | 35 | More information about PlatformIO Library Dependency Finder 36 | - http://docs.platformio.org/page/librarymanager/ldf.html 37 | -------------------------------------------------------------------------------- /platformio.ini: -------------------------------------------------------------------------------- 1 | ; PlatformIO Project Configuration File 2 | ; 3 | ; Build options: build flags, source filter 4 | ; Upload options: custom upload port, speed and extra flags 5 | ; Library options: dependencies, extra library storages 6 | ; Advanced options: extra scripting 7 | ; 8 | ; Please visit documentation for the other options and examples 9 | ; http://docs.platformio.org/page/projectconf.html 10 | 11 | ;Используется библиотека PubSubClient(imroy) 12 | 13 | [platformio] 14 | env_default = node-debug 15 | src_dir = src 16 | 17 | [common] 18 | lib_deps = 19 | Hash 20 | ArduinoJson 21 | Ticker 22 | lib_ignore = 23 | build_flags = -g -Tesp8266.flash.4m1m.ld 24 | upload_port = * ;192.168.1.128 25 | 26 | [env:node-debug] 27 | platform = espressif8266 28 | framework = arduino 29 | board = nodemcuv2 30 | lib_deps = ${common.lib_deps} 31 | lib_ignore = ${common.lib_ignore} 32 | build_flags = ${common.build_flags} -DNODEMCUV2 33 | upload_port = ${common.upload_port} 34 | -------------------------------------------------------------------------------- /src/boot.ino: -------------------------------------------------------------------------------- 1 | #include "config/include.h" 2 | 3 | void bootSetup() { 4 | ArduinoOTA.begin(); 5 | Serial.begin(SERIAL_BAUDRATE); 6 | delay(100); 7 | DEBUG_MSG("\n"); 8 | DEBUG_MSG("[BOOT] %s v.%s\n", (char *) APP_NAME, (char *) APP_VERSION); 9 | DEBUG_MSG("[BOOT] Memory size: %d bytes\n", ESP.getFlashChipSize()); 10 | DEBUG_MSG("[BOOT] Free heap: %d bytes\n", ESP.getFreeHeap()); 11 | DEBUG_MSG("[BOOT] Firmware size: %d bytes\n", ESP.getSketchSize()); 12 | DEBUG_MSG("[BOOT] Free firmware space: %d bytes\n", ESP.getFreeSketchSpace()); 13 | } 14 | -------------------------------------------------------------------------------- /src/config/debug.h: -------------------------------------------------------------------------------- 1 | #define DEBUG_PORT Serial 2 | 3 | #ifdef DEBUG_PORT 4 | #define DEBUG_MSG(...) DEBUG_PORT.printf( __VA_ARGS__ ) 5 | #else 6 | #define DEBUG_MSG(...) 7 | #endif 8 | -------------------------------------------------------------------------------- /src/config/events.h: -------------------------------------------------------------------------------- 1 | #ifndef EVENTS_H_ 2 | #define EVENTS_H_ 3 | 4 | enum { 5 | EVNT_OPEN_DOOR, 6 | EVNT_CLOSE_DOOR, 7 | EVNT_PUTDOWN_PHONE, 8 | EVNT_DOMOPHONE_WAIT, 9 | CNT_EVENTS //count of registered events 10 | }; 11 | 12 | #define MEASURE_PERIOD 20 //ms 13 | #define EVENT_DONE 0 14 | #define EVENT_CLR -1 15 | 16 | #endif //EVENTS_H_ 17 | -------------------------------------------------------------------------------- /src/config/general.h: -------------------------------------------------------------------------------- 1 | #define APP_NAME "Domophone" 2 | #define APP_VERSION "2.0.0" 3 | #define SERIAL_BAUDRATE 115200 4 | #define nop() __asm__("nop\n\t") 5 | -------------------------------------------------------------------------------- /src/config/hardware.h: -------------------------------------------------------------------------------- 1 | #define ESP_LED 2 2 | #define NODE_LED 16 3 | 4 | #define IN_PIN 14 5 | 6 | #define RELAY1 15 7 | #define RELAY2 13 8 | #define OPEN_RELAY 4 9 | -------------------------------------------------------------------------------- /src/config/include.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "debug.h" 12 | #include "general.h" 13 | #include "events.h" 14 | #include "hardware.h" 15 | #include "wifi.h" 16 | #include "mqtt.h" 17 | #include "events.h" 18 | -------------------------------------------------------------------------------- /src/config/mqtt.h: -------------------------------------------------------------------------------- 1 | #ifndef MQTT_H_ 2 | #define MQTT_H_ 3 | 4 | #include 5 | 6 | const char *mqtt_server = "m20.cloudmqtt.com"; 7 | const int mqtt_port = 12234; 8 | const char *mqtt_user = "test"; 9 | const char *mqtt_pass = "test"; 10 | 11 | const bool retained = true; 12 | 13 | String prefix = "/IoTmanager"; 14 | String deviceID = "Dom"; 15 | String ids = "e090cabf-2a89-470b-34fe-a747361a9c7d"; //your phone ids 16 | 17 | // Push notifications 18 | const char* host = "onesignal.com"; 19 | const int httpsPort = 443; 20 | String url = "/api/v1/notifications"; 21 | 22 | String msg = "Звонок в домофон"; 23 | String msg1 = "Ожидание"; 24 | String msg2 = "Открываю"; 25 | String msg3 = "Сбрасываю"; 26 | 27 | typedef struct 28 | { 29 | String sTopic; 30 | String stat; 31 | bool st; 32 | } vars_type; 33 | 34 | enum { 35 | WAIT = false, 36 | CALL = true 37 | }; 38 | 39 | enum { 40 | CALLING = 0, 41 | OPENQUIET, 42 | OPENONCE, 43 | OPENALL, 44 | RESETALL, 45 | SOUND, 46 | CONNECT, 47 | WCOUNT 48 | }; 49 | 50 | enum { 51 | ST_WAITING, 52 | ST_CALLING, 53 | ST_OPENING, 54 | ST_RESETING 55 | }; 56 | 57 | vars_type Var[WCOUNT]; 58 | bool SavedVar[WCOUNT]; 59 | String thing_config[WCOUNT]; 60 | bool DomophoneStatus = WAIT; 61 | 62 | #endif //MQTT_H_ 63 | -------------------------------------------------------------------------------- /src/config/wifi.h: -------------------------------------------------------------------------------- 1 | #ifndef WIHI_H_ 2 | #define WIHI_H_ 3 | 4 | #define SSID "wifi_ssid" 5 | #define PASSWORD "wifi_pass" 6 | 7 | #endif //WIHI_H_ 8 | -------------------------------------------------------------------------------- /src/events.ino: -------------------------------------------------------------------------------- 1 | #include "config/include.h" 2 | 3 | volatile int32_t Events[CNT_EVENTS]; 4 | 5 | Ticker timer1(RunEvents, MEASURE_PERIOD); 6 | 7 | void eventsSetup(){ 8 | ClrEvents(); 9 | timer1.start(); 10 | } 11 | 12 | void eventsloop(){ 13 | timer1.update(); 14 | 15 | if (TestEvent_Done(EVNT_OPEN_DOOR)) { 16 | OPEN(); 17 | } 18 | 19 | if (TestEvent_Done(EVNT_CLOSE_DOOR)) { 20 | CLOSE(); 21 | } 22 | 23 | if (TestEvent_Done(EVNT_PUTDOWN_PHONE)) { 24 | PICKUP_PHONE(false); 25 | CLOSE(); 26 | DOMOPHONE(Var[SOUND].st); //подключить трубку, если была включена 27 | SetEvent(EVNT_DOMOPHONE_WAIT,1000); 28 | } 29 | 30 | if (TestEvent_Done(EVNT_DOMOPHONE_WAIT)) { 31 | Serial.println("Calling status false"); 32 | setStatusCall(ST_WAITING); 33 | pubStatus(Var[CALLING].sTopic, Var[CALLING].stat); 34 | DomophoneStatus = WAIT; 35 | } 36 | } 37 | 38 | void RunEvents(){ 39 | for (uint8_t i=0; iEVENT_DONE) Events[i]--; 41 | } 42 | } 43 | 44 | void ClrEvents(){ 45 | for (uint8_t i=0; ist = s; 160 | var->stat = "{\"status\":\"" + String(s) + "\"}"; 161 | } 162 | 163 | void pubStatus(String t, String payload) { 164 | if (client.publish((t + "/status").c_str(), (uint8_t*)payload.c_str(), payload.length(), retained)) { 165 | Serial.println("Publish new status for " + t + ", value: " + payload); 166 | } else { 167 | Serial.println("Publish new status for " + t + " FAIL!"); 168 | } 169 | } 170 | 171 | void pubConfig() { 172 | bool success; 173 | for (char i = 0; i < WCOUNT-1; i++) { 174 | success = client.publish((prefix + "/" + deviceID + String(i, DEC) + "/config").c_str(), (uint8_t*)thing_config[i].c_str(), thing_config[i].length(), retained); 175 | if (success) { 176 | Serial.println("Publish config: Success (" + thing_config[i] + ")"); 177 | } else { 178 | Serial.println("Publish config FAIL! (" + thing_config[i] + ")"); 179 | } 180 | delay(150); 181 | } 182 | 183 | for (char i = 0; i < WCOUNT-1; i++) { 184 | pubStatus(Var[i].sTopic, Var[i].stat); 185 | delay(100); 186 | } 187 | } 188 | 189 | void pubConfigConnect() { 190 | bool success; 191 | success = client.publish((prefix + "/" + deviceID + "/config").c_str(), (uint8_t*)thing_config[CONNECT].c_str(), thing_config[CONNECT].length(), false); 192 | if (success) { 193 | Serial.println("Publish config: Success (" + thing_config[CONNECT] + ")"); 194 | } else { 195 | Serial.println("Publish config FAIL! (" + thing_config[CONNECT] + ")"); 196 | } 197 | } 198 | 199 | void callback(const MQTT::Publish& sub) { 200 | Serial.print("Message arrived ["); 201 | Serial.print(sub.topic()); 202 | Serial.print("] "); 203 | Serial.println(sub.payload_string()); 204 | 205 | if (sub.topic() == Var[OPENQUIET].sTopic + "/control") { 206 | changeSt = OPENQUIET; 207 | } else if (sub.topic() == Var[OPENONCE].sTopic + "/control") { 208 | changeSt = OPENONCE; 209 | } else if (sub.topic() == Var[SOUND].sTopic + "/control") { 210 | changeSt = SOUND; 211 | } else if (sub.topic() == Var[OPENALL].sTopic + "/control") { 212 | changeSt = OPENALL; 213 | } else if (sub.topic() == Var[RESETALL].sTopic + "/control") { 214 | changeSt = RESETALL; 215 | } else if (sub.topic() == prefix + "/ids") { 216 | ids = sub.payload_string(); 217 | } else if (sub.topic() == prefix) { 218 | if (sub.payload_string() == "HELLO") { 219 | pubConfigConnect(); 220 | } 221 | } 222 | 223 | if (changeSt > 0) { 224 | changeTo = !(sub.payload_string() == "0"); 225 | setStatus(&Var[changeSt], changeTo); 226 | pubStatus(Var[changeSt].sTopic, Var[changeSt].stat); 227 | switch (changeSt) { 228 | case SOUND: 229 | DOMOPHONE(Var[SOUND].st); 230 | break; 231 | case OPENQUIET: 232 | DOMOPHONE(!changeTo); 233 | case OPENONCE: 234 | case OPENALL: 235 | case RESETALL: 236 | if (Var[changeSt].st) { 237 | if (changeSt != OPENQUIET) { 238 | DOMOPHONE(Var[SOUND].st); 239 | setStatus(&Var[OPENQUIET], false); 240 | pubStatus(Var[OPENQUIET].sTopic, Var[OPENQUIET].stat); 241 | } else { 242 | SavedVar[OPENQUIET] = Var[OPENQUIET].st; 243 | if (Var[CALLING].st == ST_CALLING) { 244 | setStatusCall(ST_OPENING); 245 | pubStatus(Var[CALLING].sTopic, Var[CALLING].stat); 246 | } 247 | } 248 | if (changeSt != OPENONCE) { 249 | setStatus(&Var[OPENONCE], false); 250 | pubStatus(Var[OPENONCE].sTopic, Var[OPENONCE].stat); 251 | } else { 252 | SavedVar[OPENONCE] = Var[OPENONCE].st; 253 | if (Var[CALLING].st == ST_CALLING) { 254 | setStatusCall(ST_OPENING); 255 | pubStatus(Var[CALLING].sTopic, Var[CALLING].stat); 256 | } 257 | } 258 | if (changeSt != OPENALL) { 259 | setStatus(&Var[OPENALL], false); 260 | pubStatus(Var[OPENALL].sTopic, Var[OPENALL].stat); 261 | } else { 262 | SavedVar[OPENALL] = Var[OPENALL].st; 263 | if (Var[CALLING].st == ST_CALLING) { 264 | setStatusCall(ST_OPENING); 265 | pubStatus(Var[CALLING].sTopic, Var[CALLING].stat); 266 | } 267 | } 268 | if (changeSt != RESETALL) { 269 | setStatus(&Var[RESETALL], false); 270 | pubStatus(Var[RESETALL].sTopic, Var[RESETALL].stat); 271 | } else { 272 | SavedVar[RESETALL] = Var[RESETALL].st; 273 | if (Var[CALLING].st == ST_CALLING) { 274 | setStatusCall(ST_RESETING); 275 | pubStatus(Var[CALLING].sTopic, Var[CALLING].stat); 276 | } 277 | } 278 | } 279 | break; 280 | } 281 | changeSt = 0; 282 | } 283 | } 284 | 285 | void MQTT_loop() { 286 | if (WiFi.status() == WL_CONNECTED) { 287 | if (!client.connected()) { 288 | Serial.print("Connecting to MQTT server ... "); 289 | if (client.connect(MQTT::Connect("ESP8266Client").set_auth(mqtt_user,mqtt_pass))){ 290 | client.set_callback(callback); 291 | Serial.println("Success"); 292 | client.subscribe(prefix.c_str()); 293 | client.subscribe((prefix + "/ids").c_str()); 294 | for (char i = 1; i < WCOUNT-1; i++) { 295 | client.subscribe((Var[i].sTopic + "/control").c_str()); 296 | } 297 | pubConfig(); 298 | pubConfigConnect(); 299 | ledStatus(ESP_LED,true); 300 | } else { 301 | Serial.print("FAIL"); 302 | delay(5000); 303 | } 304 | } else { 305 | client.loop(); 306 | } 307 | } 308 | 309 | newtime = millis(); 310 | if (!DomophoneStatus) { //в режиме ожидания 311 | if (newtime - oldtime > 100) { 312 | oldtime = newtime; 313 | switchCount = 0; 314 | } else if (switchCount % 2 == 0) { 315 | if (!digitalRead(IN_PIN)) { 316 | switchCount++; 317 | oldtime = newtime; 318 | Serial.println("Call " + String(switchCount)); 319 | } 320 | } else { 321 | if (digitalRead(IN_PIN)) { 322 | switchCount++; 323 | oldtime = newtime; 324 | Serial.println("Call " + String(switchCount)); 325 | } 326 | } 327 | if (switchCount > 10) { 328 | DomophoneStatus = CALL; 329 | openCount = 0; 330 | 331 | SavedVar[OPENQUIET] = Var[OPENQUIET].st; 332 | SavedVar[OPENONCE] = Var[OPENONCE].st; 333 | SavedVar[OPENALL] = Var[OPENALL].st; 334 | SavedVar[RESETALL] = Var[RESETALL].st; 335 | 336 | if (!(SavedVar[OPENQUIET] || SavedVar[OPENONCE] || SavedVar[OPENALL] || SavedVar[RESETALL])) { 337 | push(msg); 338 | setStatusCall(ST_CALLING); 339 | } else { 340 | if (SavedVar[RESETALL]) setStatusCall(ST_RESETING); 341 | else setStatusCall(ST_OPENING); 342 | } 343 | 344 | Serial.println("Incoming call"); 345 | pubStatus(Var[CALLING].sTopic, Var[CALLING].stat); 346 | 347 | SetEvent(EVNT_DOMOPHONE_WAIT,10000); 348 | } 349 | } else { //в режиме разговора 350 | if (SavedVar[OPENQUIET] || SavedVar[OPENONCE] || SavedVar[OPENALL]) { //открыть 351 | if (openCount < 3) {//Впустить пару раз 352 | ClrEvent(EVNT_DOMOPHONE_WAIT); 353 | if (openCount == 0) PICKUP_PHONE(); //Поднять трубку 354 | if (TestEvent_Clr(EVNT_OPEN_DOOR) && TestEvent_Clr(EVNT_CLOSE_DOOR)) { 355 | SetEvent(EVNT_OPEN_DOOR,1500); 356 | SetEvent(EVNT_CLOSE_DOOR, 2500); 357 | openCount++; 358 | Serial.println("Open " + String(openCount)); 359 | } 360 | } else { 361 | if (openCount == 3) { 362 | if (TestEvent_Clr(EVNT_OPEN_DOOR) && TestEvent_Clr(EVNT_CLOSE_DOOR)) { 363 | Serial.println("Putdown phone after open"); 364 | SetEvent(EVNT_PUTDOWN_PHONE); //Повесить трубку 365 | 366 | if (SavedVar[OPENONCE]) { //Сбросить флаг открыть разово 367 | setStatus(&Var[OPENONCE], false); 368 | pubStatus(Var[OPENONCE].sTopic, Var[OPENONCE].stat); 369 | } 370 | 371 | if (SavedVar[OPENQUIET]) { //Сбросить флаг открыть разово 372 | setStatus(&Var[OPENQUIET], false); 373 | pubStatus(Var[OPENQUIET].sTopic, Var[OPENQUIET].stat); 374 | } 375 | 376 | openCount++; 377 | } 378 | } 379 | } 380 | } else if (SavedVar[RESETALL]) { //сбросить 381 | if (openCount == 0) { 382 | ClrEvent(EVNT_DOMOPHONE_WAIT); 383 | PICKUP_PHONE(); //Поднять трубку 384 | Serial.println("Putdown phone after reset"); 385 | SetEvent(EVNT_PUTDOWN_PHONE,1500); //Повесить трубку 386 | openCount++; 387 | } 388 | } else { 389 | if (!digitalRead(IN_PIN)) SetEvent(EVNT_DOMOPHONE_WAIT,10000); //низкий уровень больше 5 сек? на ожидание 390 | } 391 | } 392 | } 393 | -------------------------------------------------------------------------------- /src/relay.ino: -------------------------------------------------------------------------------- 1 | #include "config/include.h" 2 | 3 | bool relayStatus(uint8_t id) { 4 | return digitalRead(id); 5 | } 6 | 7 | bool relayStatus(uint8_t id, bool status) { 8 | digitalWrite(id, status); 9 | return status; 10 | } 11 | 12 | bool relayToggle(uint8_t id) { 13 | return relayStatus(id, !relayStatus(id)); 14 | } 15 | 16 | void relaysSetup() { 17 | pinMode(RELAY2, OUTPUT); 18 | DOMOPHONE(true); 19 | 20 | pinMode(RELAY1, OUTPUT); 21 | PICKUP_PHONE(false); 22 | 23 | pinMode(OPEN_RELAY, OUTPUT); 24 | CLOSE(); 25 | } 26 | 27 | void DOMOPHONE(bool to) { 28 | relayStatus(RELAY2, !to); 29 | } 30 | 31 | void PICKUP_PHONE() { 32 | PICKUP_PHONE(true); 33 | DOMOPHONE(false); //перекинуть реле для перехвата управления 34 | } 35 | 36 | void PICKUP_PHONE(bool to) { 37 | relayStatus(RELAY1, to); 38 | } 39 | 40 | void OPEN() { 41 | relayStatus(OPEN_RELAY, true); 42 | Serial.println("Open"); 43 | } 44 | 45 | void CLOSE() { 46 | relayStatus(OPEN_RELAY, false); 47 | Serial.println("Close"); 48 | } 49 | -------------------------------------------------------------------------------- /src/wifi.ino: -------------------------------------------------------------------------------- 1 | #include "config/include.h" 2 | 3 | IPAddress ip(192,168,1,128); 4 | IPAddress gateway(192,168,1,1); 5 | IPAddress subnet(255,255,255,0); 6 | 7 | void wifiLoop() { 8 | ArduinoOTA.handle(); 9 | if (WiFi.status() != WL_CONNECTED) { 10 | ledStatus(ESP_LED,false); 11 | DEBUG_MSG("[WIFI] Connecting to WiFi...\n"); 12 | WiFi.mode(WIFI_STA); 13 | WiFi.begin(SSID, PASSWORD); 14 | WiFi.config(ip,gateway,subnet); 15 | 16 | if (WiFi.waitForConnectResult() != WL_CONNECTED) return; 17 | IPAddress myIP = WiFi.localIP(); 18 | DEBUG_MSG("[WIFI] WiFi connected\n"); 19 | DEBUG_MSG("[WIFI] IP address: %d.%d.%d.%d\n",myIP[0],myIP[1],myIP[2],myIP[3]); 20 | } 21 | } 22 | --------------------------------------------------------------------------------