├── .gitignore ├── twitterPrinter_pio ├── lib │ ├── QRCode │ │ ├── .gitignore │ │ ├── tests │ │ │ ├── README.md │ │ │ ├── run.sh │ │ │ ├── BitBuffer.hpp │ │ │ ├── BitBuffer.cpp │ │ │ ├── run-tests.cpp │ │ │ ├── QrSegment.hpp │ │ │ ├── QrSegment.cpp │ │ │ └── QrCode.hpp │ │ ├── library.properties │ │ ├── keywords.txt │ │ ├── LICENSE.txt │ │ ├── examples │ │ │ └── QRCode │ │ │ │ └── QRCode.ino │ │ ├── src │ │ │ └── qrcode.h │ │ └── generate_table.py │ ├── pubsubclient │ │ ├── tests │ │ │ ├── testcases │ │ │ │ ├── __init__.py │ │ │ │ ├── settings.py │ │ │ │ ├── mqtt_basic.py │ │ │ │ └── mqtt_publish_in_callback.py │ │ │ ├── .gitignore │ │ │ ├── src │ │ │ │ ├── lib │ │ │ │ │ ├── trace.h │ │ │ │ │ ├── Stream.h │ │ │ │ │ ├── Buffer.h │ │ │ │ │ ├── Arduino.h │ │ │ │ │ ├── Client.h │ │ │ │ │ ├── BDDTest.h │ │ │ │ │ ├── Buffer.cpp │ │ │ │ │ ├── Stream.cpp │ │ │ │ │ ├── Print.h │ │ │ │ │ ├── IPAddress.cpp │ │ │ │ │ ├── BDDTest.cpp │ │ │ │ │ ├── ShimClient.h │ │ │ │ │ ├── IPAddress.h │ │ │ │ │ └── ShimClient.cpp │ │ │ │ ├── subscribe_spec.cpp │ │ │ │ ├── publish_spec.cpp │ │ │ │ ├── keepalive_spec.cpp │ │ │ │ ├── receive_spec.cpp │ │ │ │ └── connect_spec.cpp │ │ │ ├── Makefile │ │ │ ├── README.md │ │ │ └── testsuite.py │ │ ├── .gitignore │ │ ├── .travis.yml │ │ ├── library.properties │ │ ├── library.json │ │ ├── keywords.txt │ │ ├── LICENSE.txt │ │ ├── examples │ │ │ ├── mqtt_auth │ │ │ │ └── mqtt_auth.ino │ │ │ ├── mqtt_stream │ │ │ │ └── mqtt_stream.ino │ │ │ ├── mqtt_reconnect_nonblocking │ │ │ │ └── mqtt_reconnect_nonblocking.ino │ │ │ ├── mqtt_publish_in_callback │ │ │ │ └── mqtt_publish_in_callback.ino │ │ │ ├── mqtt_basic │ │ │ │ └── mqtt_basic.ino │ │ │ ├── mqtt_esp8266 │ │ │ │ └── mqtt_esp8266.ino │ │ │ └── mqtt_large_message │ │ │ │ └── mqtt_large_message.ino │ │ ├── README.md │ │ ├── CHANGES.txt │ │ └── src │ │ │ └── PubSubClient.h │ ├── Metro │ │ ├── examples │ │ │ ├── blinking │ │ │ │ ├── .svn │ │ │ │ │ ├── prop-base │ │ │ │ │ │ └── blinking.pde.svn-base │ │ │ │ │ ├── entries │ │ │ │ │ └── text-base │ │ │ │ │ │ └── blinking.pde.svn-base │ │ │ │ └── blinking.pde │ │ │ ├── serialInterval │ │ │ │ ├── .svn │ │ │ │ │ ├── prop-base │ │ │ │ │ │ └── serialInterval.pde.svn-base │ │ │ │ │ ├── entries │ │ │ │ │ └── text-base │ │ │ │ │ │ └── serialInterval.pde.svn-base │ │ │ │ └── serialInterval.pde │ │ │ ├── .svn │ │ │ │ ├── prop-base │ │ │ │ │ └── blinking_2_instances.zip.svn-base │ │ │ │ ├── text-base │ │ │ │ │ └── blinking_2_instances.zip.svn-base │ │ │ │ └── entries │ │ │ ├── blinking_2_instances.zip │ │ │ └── blinking_2_instances │ │ │ │ ├── .svn │ │ │ │ ├── entries │ │ │ │ └── text-base │ │ │ │ │ └── blinking_2_instances.pde.svn-base │ │ │ │ └── blinking_2_instances.pde │ │ ├── Metro.pdf │ │ ├── about.txt │ │ ├── src │ │ │ ├── Metro.h │ │ │ └── Metro.cpp │ │ └── keywords.txt │ ├── readme.txt │ └── ESPHelper_Utils │ │ └── ESPHelper_base.h ├── .gitignore ├── platformio.ini ├── README.txt ├── .travis.yml └── src │ └── twitterPrinter.ino ├── requirements.txt ├── twitterTags.txt ├── twitterScraper.py └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | /twitterPrinter_pio/.vscode 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/QRCode/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | paho-mqtt 2 | unidecode 3 | python-twitter 4 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/pubsubclient/tests/testcases/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /twitterTags.txt: -------------------------------------------------------------------------------- 1 | #puppies 2 | #programming 3 | #esp8266 4 | @itkindaworksinc -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/pubsubclient/tests/.gitignore: -------------------------------------------------------------------------------- 1 | .build 2 | tmpbin 3 | logs 4 | *.pyc 5 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/pubsubclient/tests/testcases/settings.py: -------------------------------------------------------------------------------- 1 | server_ip = "172.16.0.2" 2 | arduino_ip = "172.16.0.100" 3 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/Metro/examples/blinking/.svn/prop-base/blinking.pde.svn-base: -------------------------------------------------------------------------------- 1 | K 14 2 | svn:executable 3 | V 0 4 | 5 | END 6 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/pubsubclient/.gitignore: -------------------------------------------------------------------------------- 1 | tests/bin 2 | .pioenvs 3 | .piolibdeps 4 | .clang_complete 5 | .gcc-flags.json 6 | -------------------------------------------------------------------------------- /twitterPrinter_pio/.gitignore: -------------------------------------------------------------------------------- 1 | .pio 2 | .vscode/.browse.c_cpp.db* 3 | .vscode/c_cpp_properties.json 4 | .vscode/launch.json 5 | .vscode/ipch 6 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/Metro/examples/serialInterval/.svn/prop-base/serialInterval.pde.svn-base: -------------------------------------------------------------------------------- 1 | K 14 2 | svn:executable 3 | V 0 4 | 5 | END 6 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/Metro/Metro.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItKindaWorks/ESP8266-TwitterPrinter/master/twitterPrinter_pio/lib/Metro/Metro.pdf -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/Metro/about.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItKindaWorks/ESP8266-TwitterPrinter/master/twitterPrinter_pio/lib/Metro/about.txt -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/Metro/examples/.svn/prop-base/blinking_2_instances.zip.svn-base: -------------------------------------------------------------------------------- 1 | K 13 2 | svn:mime-type 3 | V 24 4 | application/octet-stream 5 | END 6 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/pubsubclient/.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: cpp 3 | compiler: 4 | - g++ 5 | script: cd tests && make && make test 6 | os: 7 | - linux 8 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/Metro/examples/blinking_2_instances.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItKindaWorks/ESP8266-TwitterPrinter/master/twitterPrinter_pio/lib/Metro/examples/blinking_2_instances.zip -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/Metro/examples/.svn/text-base/blinking_2_instances.zip.svn-base: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItKindaWorks/ESP8266-TwitterPrinter/master/twitterPrinter_pio/lib/Metro/examples/.svn/text-base/blinking_2_instances.zip.svn-base -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/QRCode/tests/README.md: -------------------------------------------------------------------------------- 1 | Testing 2 | ======= 3 | 4 | The testcases work by using the Nayuki QR code generating library, generating a QR code 5 | in both libraries and comparing them. 6 | 7 | Running 8 | ------- 9 | 10 | ``` 11 | ./run.sh 12 | ``` 13 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/QRCode/tests/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | clang++ run-tests.cpp QrCode.cpp QrSegment.cpp BitBuffer.cpp ../src/qrcode.c -o test && ./test 4 | clang++ run-tests.cpp QrCode.cpp QrSegment.cpp BitBuffer.cpp ../src/qrcode.c -o test -D LOCK_VERSION=3 && ./test 5 | 6 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/pubsubclient/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 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/QRCode/library.properties: -------------------------------------------------------------------------------- 1 | name=QRCode 2 | version=0.0.1 3 | author=Richard Moore 4 | maintainer=Richard Moore 5 | sentence=A simple QR code generation library. 6 | paragraph=A simple QR code generation library. 7 | category=Other 8 | url=https://github.com/ricmoo/qrcode/ 9 | architectures=* 10 | includes=qrcode.h 11 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/pubsubclient/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 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/pubsubclient/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 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/Metro/src/Metro.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifndef Metro_h 4 | #define Metro_h 5 | 6 | #include 7 | 8 | class Metro 9 | { 10 | 11 | public: 12 | Metro(unsigned long interval_millis); 13 | Metro(unsigned long interval_millis, uint8_t autoreset); 14 | void interval(unsigned long interval_millis); 15 | unsigned long checkMillis(); 16 | char check(); 17 | void reset(); 18 | 19 | private: 20 | uint8_t autoreset; 21 | unsigned long previous_millis, interval_millis; 22 | 23 | }; 24 | 25 | #endif 26 | 27 | 28 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/pubsubclient/tests/src/lib/Arduino.h: -------------------------------------------------------------------------------- 1 | #ifndef Arduino_h 2 | #define Arduino_h 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "Print.h" 9 | 10 | 11 | extern "C"{ 12 | typedef uint8_t byte ; 13 | typedef uint8_t boolean ; 14 | 15 | /* sketch */ 16 | extern void setup( void ) ; 17 | extern void loop( void ) ; 18 | uint32_t millis( void ); 19 | } 20 | 21 | #define PROGMEM 22 | #define pgm_read_byte_near(x) *(x) 23 | 24 | #define yield(x) {} 25 | 26 | #endif // Arduino_h 27 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/QRCode/keywords.txt: -------------------------------------------------------------------------------- 1 | 2 | # Datatypes (KEYWORD1) 3 | 4 | bool KEYWORD1 5 | uint8_t KEYWORD1 6 | QRCode KEYWORD1 7 | 8 | 9 | # Methods and Functions (KEYWORD2) 10 | 11 | qrcode_getBufferSize KEYWORD2 12 | qrcode_initText KEYWORD2 13 | qrcode_initBytes KEYWORD2 14 | qrcode_getModule KEYWORD2 15 | 16 | 17 | # Instances (KEYWORD2) 18 | 19 | 20 | # Constants (LITERAL1) 21 | 22 | false LITERAL1 23 | true LITERAL1 24 | 25 | ECC_LOW LITERAL1 26 | ECC_MEDIUM LITERAL1 27 | ECC_QUARTILE LITERAL1 28 | ECC_HIGH LITERAL1 29 | MODE_NUMERIC LITERAL1 30 | MODE_ALPHANUMERIC LITERAL1 31 | MODE_BYTE LITERAL1 32 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/pubsubclient/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=../src/PubSubClient.cpp 8 | CC=g++ 9 | CFLAGS=-I${SRC_PATH}/lib -I../src 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 | 20 | test: 21 | @bin/connect_spec 22 | @bin/publish_spec 23 | @bin/receive_spec 24 | @bin/subscribe_spec 25 | @bin/keepalive_spec 26 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/pubsubclient/library.properties: -------------------------------------------------------------------------------- 1 | name=PubSubClient 2 | version=2.7 3 | author=Nick O'Leary 4 | maintainer=Nick O'Leary 5 | sentence=A client library for MQTT messaging. 6 | paragraph=MQTT is a lightweight messaging protocol ideal for small devices. This library allows you to send and receive MQTT messages. It supports the latest MQTT 3.1.1 protocol and can be configured to use the older MQTT 3.1 if needed. It supports all Arduino Ethernet Client compatible hardware, including the Intel Galileo/Edison, ESP8266 and TI CC3000. 7 | category=Communication 8 | url=http://pubsubclient.knolleary.net 9 | architectures=* 10 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/pubsubclient/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 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/Metro/keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For Test 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | Metro KEYWORD1 10 | 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | 15 | check KEYWORD2 16 | interval KEYWORD2 17 | 18 | ####################################### 19 | # Instances (KEYWORD2) 20 | ####################################### 21 | 22 | ####################################### 23 | # Constants (LITERAL1) 24 | ####################################### 25 | 26 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/pubsubclient/tests/src/lib/BDDTest.h: -------------------------------------------------------------------------------- 1 | #ifndef bddtest_h 2 | #define bddtest_h 3 | 4 | void bddtest_suite(const char* name); 5 | int bddtest_test(const char*, int, const char*, int); 6 | void bddtest_start(const char*); 7 | void bddtest_end(); 8 | int bddtest_summary(); 9 | 10 | #define SUITE(x) { bddtest_suite(x); } 11 | #define TEST(x) { if (!bddtest_test(__FILE__, __LINE__, #x, (x))) return false; } 12 | 13 | #define IT(x) { bddtest_start(x); } 14 | #define END_IT { bddtest_end();return true;} 15 | 16 | #define FINISH { return bddtest_summary(); } 17 | 18 | #define IS_TRUE(x) TEST(x) 19 | #define IS_FALSE(x) TEST(!(x)) 20 | #define IS_EQUAL(x,y) TEST(x==y) 21 | #define IS_NOT_EQUAL(x,y) TEST(x!=y) 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/Metro/examples/blinking/.svn/entries: -------------------------------------------------------------------------------- 1 | 10 2 | 3 | dir 4 | 1 5 | file://localhost/Users/cromer/Documents/SVN/test/Arduino/libraries/Metro/examples/blinking 6 | file://localhost/Users/cromer/Documents/SVN/test 7 | 8 | 9 | 10 | 2012-12-13T10:12:28.693182Z 11 | 1 12 | cromer 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | f0375619-656b-4b81-92d1-34963d12e3ad 28 | 29 | blinking.pde 30 | file 31 | 32 | 33 | 34 | 35 | 2012-12-13T10:16:05.000000Z 36 | ac9d1a0c28f8d5cce96f5960afc3c177 37 | 2012-12-13T10:12:28.693182Z 38 | 1 39 | cromer 40 | has-props 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 858 62 | 63 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/Metro/examples/serialInterval/.svn/entries: -------------------------------------------------------------------------------- 1 | 10 2 | 3 | dir 4 | 1 5 | file://localhost/Users/cromer/Documents/SVN/test/Arduino/libraries/Metro/examples/serialInterval 6 | file://localhost/Users/cromer/Documents/SVN/test 7 | 8 | 9 | 10 | 2012-12-13T10:12:28.693182Z 11 | 1 12 | cromer 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | f0375619-656b-4b81-92d1-34963d12e3ad 28 | 29 | serialInterval.pde 30 | file 31 | 32 | 33 | 34 | 35 | 2012-12-13T10:16:05.000000Z 36 | 2451aaf3c262d3ddebf7f8274db473ef 37 | 2012-12-13T10:12:28.693182Z 38 | 1 39 | cromer 40 | has-props 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 646 62 | 63 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/Metro/examples/blinking_2_instances/.svn/entries: -------------------------------------------------------------------------------- 1 | 10 2 | 3 | dir 4 | 1 5 | file://localhost/Users/cromer/Documents/SVN/test/Arduino/libraries/Metro/examples/blinking_2_instances 6 | file://localhost/Users/cromer/Documents/SVN/test 7 | 8 | 9 | 10 | 2012-12-13T10:12:28.693182Z 11 | 1 12 | cromer 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | f0375619-656b-4b81-92d1-34963d12e3ad 28 | 29 | blinking_2_instances.pde 30 | file 31 | 32 | 33 | 34 | 35 | 2012-12-13T10:16:05.000000Z 36 | 1e087c88cd4fbeaa3b01ed60f02c2c46 37 | 2012-12-13T10:12:28.693182Z 38 | 1 39 | cromer 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 1078 62 | 63 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/pubsubclient/tests/src/lib/Buffer.cpp: -------------------------------------------------------------------------------- 1 | #include "Buffer.h" 2 | #include "Arduino.h" 3 | 4 | Buffer::Buffer() { 5 | this->pos = 0; 6 | this->length = 0; 7 | } 8 | 9 | Buffer::Buffer(uint8_t* buf, size_t size) { 10 | this->pos = 0; 11 | this->length = 0; 12 | this->add(buf,size); 13 | } 14 | bool Buffer::available() { 15 | return this->pos < this->length; 16 | } 17 | 18 | uint8_t Buffer::next() { 19 | if (this->available()) { 20 | return this->buffer[this->pos++]; 21 | } 22 | return 0; 23 | } 24 | 25 | void Buffer::reset() { 26 | this->pos = 0; 27 | } 28 | 29 | void Buffer::add(uint8_t* buf, size_t size) { 30 | uint16_t i = 0; 31 | for (;ibuffer[this->length++] = buf[i]; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/Metro/examples/serialInterval/serialInterval.pde: -------------------------------------------------------------------------------- 1 | // This example sends a Serial message every 250 milliseconds 2 | 3 | #include // Include the Metro library 4 | 5 | Metro serialMetro = Metro(250); // Instantiate an instance 6 | 7 | void setup() { 8 | Serial.begin(115200); // Start the Serial communication 9 | } 10 | 11 | void loop() { 12 | 13 | if (serialMetro.check() == 1) { // check if the metro has passed it's interval . 14 | // Output all the analog readings seperated by a space character 15 | for (int i = 0; i < 6; i++ ) { 16 | Serial.print (analogRead( i) ); 17 | Serial.print(32,BYTE); 18 | } 19 | // Terminate message with a linefeed and a carriage return 20 | Serial.print(13,BYTE); 21 | Serial.print(10,BYTE); 22 | } 23 | } 24 | 25 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/Metro/examples/serialInterval/.svn/text-base/serialInterval.pde.svn-base: -------------------------------------------------------------------------------- 1 | // This example sends a Serial message every 250 milliseconds 2 | 3 | #include // Include the Metro library 4 | 5 | Metro serialMetro = Metro(250); // Instantiate an instance 6 | 7 | void setup() { 8 | Serial.begin(115200); // Start the Serial communication 9 | } 10 | 11 | void loop() { 12 | 13 | if (serialMetro.check() == 1) { // check if the metro has passed it's interval . 14 | // Output all the analog readings seperated by a space character 15 | for (int i = 0; i < 6; i++ ) { 16 | Serial.print (analogRead( i) ); 17 | Serial.print(32,BYTE); 18 | } 19 | // Terminate message with a linefeed and a carriage return 20 | Serial.print(13,BYTE); 21 | Serial.print(10,BYTE); 22 | } 23 | } 24 | 25 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/Metro/examples/.svn/entries: -------------------------------------------------------------------------------- 1 | 10 2 | 3 | dir 4 | 1 5 | file://localhost/Users/cromer/Documents/SVN/test/Arduino/libraries/Metro/examples 6 | file://localhost/Users/cromer/Documents/SVN/test 7 | 8 | 9 | 10 | 2012-12-13T10:12:28.693182Z 11 | 1 12 | cromer 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | f0375619-656b-4b81-92d1-34963d12e3ad 28 | 29 | serialInterval 30 | dir 31 | 32 | blinking_2_instances 33 | dir 34 | 35 | blinking_2_instances.zip 36 | file 37 | 38 | 39 | 40 | 41 | 2012-12-13T10:16:05.000000Z 42 | fbea96ad11d4822b30d8f570fa6e23ab 43 | 2012-12-13T10:12:28.693182Z 44 | 1 45 | cromer 46 | has-props 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 810 68 | 69 | blinking 70 | dir 71 | 72 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/pubsubclient/library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "PubSubClient", 3 | "keywords": "ethernet, mqtt, m2m, iot", 4 | "description": "A client library for MQTT messaging. MQTT is a lightweight messaging protocol ideal for small devices. This library allows you to send and receive MQTT messages. It supports the latest MQTT 3.1.1 protocol and can be configured to use the older MQTT 3.1 if needed. It supports all Arduino Ethernet Client compatible hardware, including the Intel Galileo/Edison, ESP8266 and TI CC3000.", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/knolleary/pubsubclient.git" 8 | }, 9 | "version": "2.7", 10 | "exclude": "tests", 11 | "examples": "examples/*/*.ino", 12 | "frameworks": "arduino", 13 | "platforms": [ 14 | "atmelavr", 15 | "espressif" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /twitterPrinter_pio/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 | [env:d1_mini] 12 | board = d1_mini ; board = esp01 13 | framework = arduino 14 | platform = espressif8266@^2 15 | lib_ldf_mode = deep+ 16 | 17 | lib_deps = 18 | PubSubClient @ 2.7 19 | itkindaworks/ESPHelper @ ^1.7.6 20 | ArduinoJson @ 6.17.0 21 | adafruit/Adafruit Thermal Printer Library @ ^1.4.0 22 | Bounce2 23 | 24 | monitor_speed = 115200 25 | 26 | upload_flags = 27 | --port=8266 28 | --auth=mauimaui 29 | upload_port = 192.168.2.216 30 | ; upload_port = /dev/cu.usbserial-1430 31 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/pubsubclient/keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For PubSubClient 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | PubSubClient KEYWORD1 10 | 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | 15 | connect KEYWORD2 16 | disconnect KEYWORD2 17 | publish KEYWORD2 18 | publish_P KEYWORD2 19 | beginPublish KEYWORD2 20 | endPublish KEYWORD2 21 | write KEYWORD2 22 | subscribe KEYWORD2 23 | unsubscribe KEYWORD2 24 | loop KEYWORD2 25 | connected KEYWORD2 26 | setServer KEYWORD2 27 | setCallback KEYWORD2 28 | setClient KEYWORD2 29 | setStream KEYWORD2 30 | 31 | ####################################### 32 | # Constants (LITERAL1) 33 | ####################################### 34 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/pubsubclient/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 | -------------------------------------------------------------------------------- /twitterPrinter_pio/README.txt: -------------------------------------------------------------------------------- 1 | 2 | NOTE: This is a Platform IO project folder. Please visit https://platformio.org/ if you do not have an IDE with Platform IO installed already. 3 | 4 | 5 | This project is intended to be used with a thermal printer like the one shown here: https://www.adafruit.com/product/597 6 | 7 | The serial pins for this project are D5 and D6 for RX and TX respectivly. This can be changed to your preferred pins though. 8 | 9 | 10 | To use this program, 11 | 1. flash your ESP type device and wait for it to boot up. The first time it boots it will not have any wifi or mqtt settings. 12 | 13 | 2. To fix this, join the network created by the device (it should be something like "NEW-ESP-HOTSPOT") 14 | 15 | 3. Once connected, open http://192.168.1.1 in your browser and set the desired topic, then go to http://192.168.1.1/config and set your wifi and mqtt credentials 16 | 17 | 4. Now you should be all set to go. You can test by running the twitterScraper.py program included in this package and it should print out a recent tweet. 18 | 19 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/Metro/examples/blinking/blinking.pde: -------------------------------------------------------------------------------- 1 | /* 2 | This code will blink an LED attached to pin 13 on and off. 3 | It will stay on for 0.25 seconds. 4 | It will stay off for 1 second. 5 | */ 6 | #include //Include Metro library 7 | #define LED 13 // Define the led's pin 8 | 9 | //Create a variable to hold theled's current state 10 | int state = HIGH; 11 | 12 | // Instanciate a metro object and set the interval to 250 milliseconds (0.25 seconds). 13 | Metro ledMetro = Metro(250); 14 | 15 | void setup() 16 | { 17 | pinMode(LED,OUTPUT); 18 | digitalWrite(LED,state); 19 | } 20 | 21 | void loop() 22 | { 23 | 24 | if (ledMetro.check() == 1) { // check if the metro has passed its interval . 25 | if (state==HIGH) { 26 | state=LOW; 27 | ledMetro.interval(250); // if the pin is HIGH, set the interval to 0.25 seconds. 28 | } 29 | else { 30 | ledMetro.interval(1000); // if the pin is LOW, set the interval to 1 second. 31 | state=HIGH; 32 | } 33 | digitalWrite(LED,state); 34 | } 35 | } 36 | 37 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/Metro/examples/blinking/.svn/text-base/blinking.pde.svn-base: -------------------------------------------------------------------------------- 1 | /* 2 | This code will blink an LED attached to pin 13 on and off. 3 | It will stay on for 0.25 seconds. 4 | It will stay off for 1 second. 5 | */ 6 | #include //Include Metro library 7 | #define LED 13 // Define the led's pin 8 | 9 | //Create a variable to hold theled's current state 10 | int state = HIGH; 11 | 12 | // Instanciate a metro object and set the interval to 250 milliseconds (0.25 seconds). 13 | Metro ledMetro = Metro(250); 14 | 15 | void setup() 16 | { 17 | pinMode(LED,OUTPUT); 18 | digitalWrite(LED,state); 19 | } 20 | 21 | void loop() 22 | { 23 | 24 | if (ledMetro.check() == 1) { // check if the metro has passed its interval . 25 | if (state==HIGH) { 26 | state=LOW; 27 | ledMetro.interval(250); // if the pin is HIGH, set the interval to 0.25 seconds. 28 | } 29 | else { 30 | ledMetro.interval(1000); // if the pin is LOW, set the interval to 1 second. 31 | state=HIGH; 32 | } 33 | digitalWrite(LED,state); 34 | } 35 | } 36 | 37 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/pubsubclient/tests/src/lib/Print.h: -------------------------------------------------------------------------------- 1 | /* 2 | Print.h - Base class that provides print() and println() 3 | Copyright (c) 2008 David A. Mellis. All right reserved. 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 St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef Print_h 21 | #define Print_h 22 | 23 | class Print { 24 | public: 25 | virtual size_t write(uint8_t) = 0; 26 | }; 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/pubsubclient/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2008-2015 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 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/pubsubclient/tests/src/lib/IPAddress.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | IPAddress::IPAddress() 6 | { 7 | memset(_address, 0, sizeof(_address)); 8 | } 9 | 10 | IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet) 11 | { 12 | _address[0] = first_octet; 13 | _address[1] = second_octet; 14 | _address[2] = third_octet; 15 | _address[3] = fourth_octet; 16 | } 17 | 18 | IPAddress::IPAddress(uint32_t address) 19 | { 20 | memcpy(_address, &address, sizeof(_address)); 21 | } 22 | 23 | IPAddress::IPAddress(const uint8_t *address) 24 | { 25 | memcpy(_address, address, sizeof(_address)); 26 | } 27 | 28 | IPAddress& IPAddress::operator=(const uint8_t *address) 29 | { 30 | memcpy(_address, address, sizeof(_address)); 31 | return *this; 32 | } 33 | 34 | IPAddress& IPAddress::operator=(uint32_t address) 35 | { 36 | memcpy(_address, (const uint8_t *)&address, sizeof(_address)); 37 | return *this; 38 | } 39 | 40 | bool IPAddress::operator==(const uint8_t* addr) 41 | { 42 | return memcmp(addr, _address, sizeof(_address)) == 0; 43 | } 44 | 45 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/QRCode/LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Richard Moore 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /twitterPrinter_pio/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 | | | 12 | | |--Bar 13 | | | |--docs 14 | | | |--examples 15 | | | |--src 16 | | | |- Bar.c 17 | | | |- Bar.h 18 | | | |- library.json (optional, custom build options, etc) http://docs.platformio.org/page/librarymanager/config.html 19 | | | 20 | | |--Foo 21 | | | |- Foo.c 22 | | | |- Foo.h 23 | | | 24 | | |- readme.txt --> THIS FILE 25 | | 26 | |- platformio.ini 27 | |--src 28 | |- main.c 29 | 30 | Then in `src/main.c` you should use: 31 | 32 | #include 33 | #include 34 | 35 | // rest H/C/CPP code 36 | 37 | PlatformIO will find your libraries automatically, configure preprocessor's 38 | include paths and build them. 39 | 40 | More information about PlatformIO Library Dependency Finder 41 | - http://docs.platformio.org/page/librarymanager/ldf.html 42 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/pubsubclient/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 | #include 13 | 14 | // Update these with values suitable for your network. 15 | byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; 16 | IPAddress ip(172, 16, 0, 100); 17 | IPAddress server(172, 16, 0, 2); 18 | 19 | void callback(char* topic, byte* payload, unsigned int length) { 20 | // handle message arrived 21 | } 22 | 23 | EthernetClient ethClient; 24 | PubSubClient client(server, 1883, callback, ethClient); 25 | 26 | void setup() 27 | { 28 | Ethernet.begin(mac, ip); 29 | // Note - the default maximum packet size is 128 bytes. If the 30 | // combined length of clientId, username and password exceed this, 31 | // you will need to increase the value of MQTT_MAX_PACKET_SIZE in 32 | // PubSubClient.h 33 | 34 | if (client.connect("arduinoClient", "testuser", "testpass")) { 35 | client.publish("outTopic","hello world"); 36 | client.subscribe("inTopic"); 37 | } 38 | } 39 | 40 | void loop() 41 | { 42 | client.loop(); 43 | } 44 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/Metro/examples/blinking_2_instances/blinking_2_instances.pde: -------------------------------------------------------------------------------- 1 | // This code will blink output 13 every 250 ms 2 | // abd will blink output 9 every 125 ms 3 | 4 | 5 | #include // Include Metro library 6 | #define LED0 13 // Define a LED pin 7 | #define LED1 9 // Define another LED pin 8 | 9 | // Create variables to hold the LED states 10 | int state0 = HIGH; 11 | int state1 = HIGH; 12 | 13 | // Instantiate a metro object and set the interval to 250 milliseconds (0.25 seconds). 14 | Metro metro0 = Metro(500); 15 | 16 | // Instantiate another metro object and set the interval to 125 milliseconds (0.125 seconds). 17 | Metro metro1 = Metro(125); 18 | 19 | void setup() 20 | { 21 | pinMode(LED0,OUTPUT); 22 | digitalWrite(LED0,state0); 23 | 24 | pinMode(LED1,OUTPUT); 25 | digitalWrite(LED1,state1); 26 | 27 | } 28 | 29 | void loop() 30 | { 31 | 32 | if (metro0.check() == 1) { // check if the metro has passed its interval . 33 | if (state0==HIGH) { 34 | state0=LOW; 35 | } else { 36 | state0=HIGH; 37 | } 38 | digitalWrite(LED0,state0); 39 | } 40 | 41 | if (metro1.check() == 1) { // check if the metro has passed its interval . 42 | if (state1==HIGH) { 43 | state1=LOW; 44 | } else { 45 | state1=HIGH; 46 | } 47 | digitalWrite(LED1,state1); 48 | } 49 | 50 | 51 | } 52 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/Metro/examples/blinking_2_instances/.svn/text-base/blinking_2_instances.pde.svn-base: -------------------------------------------------------------------------------- 1 | // This code will blink output 13 every 250 ms 2 | // abd will blink output 9 every 125 ms 3 | 4 | 5 | #include // Include Metro library 6 | #define LED0 13 // Define a LED pin 7 | #define LED1 9 // Define another LED pin 8 | 9 | // Create variables to hold the LED states 10 | int state0 = HIGH; 11 | int state1 = HIGH; 12 | 13 | // Instantiate a metro object and set the interval to 250 milliseconds (0.25 seconds). 14 | Metro metro0 = Metro(500); 15 | 16 | // Instantiate another metro object and set the interval to 125 milliseconds (0.125 seconds). 17 | Metro metro1 = Metro(125); 18 | 19 | void setup() 20 | { 21 | pinMode(LED0,OUTPUT); 22 | digitalWrite(LED0,state0); 23 | 24 | pinMode(LED1,OUTPUT); 25 | digitalWrite(LED1,state1); 26 | 27 | } 28 | 29 | void loop() 30 | { 31 | 32 | if (metro0.check() == 1) { // check if the metro has passed its interval . 33 | if (state0==HIGH) { 34 | state0=LOW; 35 | } else { 36 | state0=HIGH; 37 | } 38 | digitalWrite(LED0,state0); 39 | } 40 | 41 | if (metro1.check() == 1) { // check if the metro has passed its interval . 42 | if (state1==HIGH) { 43 | state1=LOW; 44 | } else { 45 | state1=HIGH; 46 | } 47 | digitalWrite(LED1,state1); 48 | } 49 | 50 | 51 | } 52 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/pubsubclient/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 | void bddtest_suite(const char* name) { 15 | LOG(name << "\n"); 16 | } 17 | 18 | int bddtest_test(const char* file, int line, const char* assertion, int result) { 19 | if (!result) { 20 | LOG("✗\n"); 21 | std::ostringstream os; 22 | os << " ! "<::iterator it = failureList.begin(); it != failureList.end(); it++) { 40 | LOG("\n"); 41 | LOG(*it); 42 | LOG("\n"); 43 | } 44 | 45 | LOG(std::dec << testPasses << "/" << testCount << " tests passed\n\n"); 46 | if (testPasses == testCount) { 47 | return 0; 48 | } 49 | return 1; 50 | } 51 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/pubsubclient/tests/testcases/mqtt_basic.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import settings 3 | import time 4 | import mosquitto 5 | 6 | 7 | def on_message(mosq, obj, msg): 8 | obj.message_queue.append(msg) 9 | 10 | 11 | class mqtt_basic(unittest.TestCase): 12 | 13 | message_queue = [] 14 | 15 | @classmethod 16 | def setUpClass(self): 17 | self.client = mosquitto.Mosquitto("pubsubclient_ut", clean_session=True, obj=self) 18 | self.client.connect(settings.server_ip) 19 | self.client.on_message = on_message 20 | self.client.subscribe("outTopic", 0) 21 | 22 | @classmethod 23 | def tearDownClass(self): 24 | self.client.disconnect() 25 | 26 | def test_one(self): 27 | i = 30 28 | while len(self.message_queue) == 0 and i > 0: 29 | self.client.loop() 30 | time.sleep(0.5) 31 | i -= 1 32 | self.assertTrue(i > 0, "message receive timed-out") 33 | self.assertEqual(len(self.message_queue), 1, "unexpected number of messages received") 34 | msg = self.message_queue[0] 35 | self.assertEqual(msg.mid, 0, "message id not 0") 36 | self.assertEqual(msg.topic, "outTopic", "message topic incorrect") 37 | self.assertEqual(msg.payload, "hello world") 38 | self.assertEqual(msg.qos, 0, "message qos not 0") 39 | self.assertEqual(msg.retain, False, "message retain flag incorrect") 40 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/QRCode/examples/QRCode/QRCode.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * QRCode 3 | * 4 | * A quick example of generating a QR code. 5 | * 6 | * This prints the QR code to the serial monitor as solid blocks. Each module 7 | * is two characters wide, since the monospace font used in the serial monitor 8 | * is approximately twice as tall as wide. 9 | * 10 | */ 11 | 12 | #include "qrcode.h" 13 | 14 | void setup() { 15 | Serial.begin(115200); 16 | 17 | // Start time 18 | uint32_t dt = millis(); 19 | 20 | // Create the QR code 21 | QRCode qrcode; 22 | uint8_t qrcodeData[qrcode_getBufferSize(3)]; 23 | qrcode_initText(&qrcode, qrcodeData, 3, 0, "HELLO WORLD"); 24 | 25 | // Delta time 26 | dt = millis() - dt; 27 | Serial.print("QR Code Generation Time: "); 28 | Serial.print(dt); 29 | Serial.print("\n"); 30 | 31 | // Top quiet zone 32 | Serial.print("\n\n\n\n"); 33 | 34 | for (uint8_t y = 0; y < qrcode.size; y++) { 35 | 36 | // Left quiet zone 37 | Serial.print(" "); 38 | 39 | // Each horizontal module 40 | for (uint8_t x = 0; x < qrcode.size; x++) { 41 | 42 | // Print each module (UTF-8 \u2588 is a solid block) 43 | Serial.print(qrcode_getModule(&qrcode, x, y) ? "\u2588\u2588": " "); 44 | 45 | } 46 | 47 | Serial.print("\n"); 48 | } 49 | 50 | // Bottom quiet zone 51 | Serial.print("\n\n\n\n"); 52 | } 53 | 54 | void loop() { 55 | 56 | } 57 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/pubsubclient/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 | #include 16 | 17 | // Update these with values suitable for your network. 18 | byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; 19 | IPAddress ip(172, 16, 0, 100); 20 | IPAddress server(172, 16, 0, 2); 21 | 22 | SRAM sram(4, SRAM_1024); 23 | 24 | void callback(char* topic, byte* payload, unsigned int length) { 25 | sram.seek(1); 26 | 27 | // do something with the message 28 | for(uint8_t i=0; i 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 | # install: 32 | # - pip install -U platformio 33 | # 34 | # script: 35 | # - platformio run 36 | 37 | 38 | # 39 | # Template #2: The project is intended to by used as a library with examples 40 | # 41 | 42 | # language: python 43 | # python: 44 | # - "2.7" 45 | # 46 | # env: 47 | # - PLATFORMIO_CI_SRC=path/to/test/file.c 48 | # - PLATFORMIO_CI_SRC=examples/file.ino 49 | # - PLATFORMIO_CI_SRC=path/to/test/directory 50 | # 51 | # install: 52 | # - pip install -U platformio 53 | # 54 | # script: 55 | # - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N 56 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/pubsubclient/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Reconnecting MQTT example - non-blocking 3 | 4 | This sketch demonstrates how to keep the client connected 5 | using a non-blocking reconnect function. If the client loses 6 | its connection, it attempts to reconnect every 5 seconds 7 | without blocking the main loop. 8 | 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | // Update these with values suitable for your hardware/network. 16 | byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; 17 | IPAddress ip(172, 16, 0, 100); 18 | IPAddress server(172, 16, 0, 2); 19 | 20 | void callback(char* topic, byte* payload, unsigned int length) { 21 | // handle message arrived 22 | } 23 | 24 | EthernetClient ethClient; 25 | PubSubClient client(ethClient); 26 | 27 | long lastReconnectAttempt = 0; 28 | 29 | boolean reconnect() { 30 | if (client.connect("arduinoClient")) { 31 | // Once connected, publish an announcement... 32 | client.publish("outTopic","hello world"); 33 | // ... and resubscribe 34 | client.subscribe("inTopic"); 35 | } 36 | return client.connected(); 37 | } 38 | 39 | void setup() 40 | { 41 | client.setServer(server, 1883); 42 | client.setCallback(callback); 43 | 44 | Ethernet.begin(mac, ip); 45 | delay(1500); 46 | lastReconnectAttempt = 0; 47 | } 48 | 49 | 50 | void loop() 51 | { 52 | if (!client.connected()) { 53 | long now = millis(); 54 | if (now - lastReconnectAttempt > 5000) { 55 | lastReconnectAttempt = now; 56 | // Attempt to reconnect 57 | if (reconnect()) { 58 | lastReconnectAttempt = 0; 59 | } 60 | } 61 | } else { 62 | // Client connected 63 | 64 | client.loop(); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/pubsubclient/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 | #include 20 | 21 | // Update these with values suitable for your network. 22 | byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; 23 | IPAddress ip(172, 16, 0, 100); 24 | IPAddress server(172, 16, 0, 2); 25 | 26 | // Callback function header 27 | void callback(char* topic, byte* payload, unsigned int length); 28 | 29 | EthernetClient ethClient; 30 | PubSubClient client(server, 1883, callback, ethClient); 31 | 32 | // Callback function 33 | void callback(char* topic, byte* payload, unsigned int length) { 34 | // In order to republish this payload, a copy must be made 35 | // as the orignal payload buffer will be overwritten whilst 36 | // constructing the PUBLISH packet. 37 | 38 | // Allocate the correct amount of memory for the payload copy 39 | byte* p = (byte*)malloc(length); 40 | // Copy the payload to the new buffer 41 | memcpy(p,payload,length); 42 | client.publish("outTopic", p, length); 43 | // Free the memory 44 | free(p); 45 | } 46 | 47 | void setup() 48 | { 49 | 50 | Ethernet.begin(mac, ip); 51 | if (client.connect("arduinoClient")) { 52 | client.publish("outTopic","hello world"); 53 | client.subscribe("inTopic"); 54 | } 55 | } 56 | 57 | void loop() 58 | { 59 | client.loop(); 60 | } 61 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/pubsubclient/README.md: -------------------------------------------------------------------------------- 1 | # Arduino Client for MQTT 2 | 3 | This library provides a client for doing simple publish/subscribe messaging with 4 | a server that supports MQTT. 5 | 6 | ## Examples 7 | 8 | The library comes with a number of example sketches. See File > Examples > PubSubClient 9 | within the Arduino application. 10 | 11 | Full API documentation is available here: https://pubsubclient.knolleary.net 12 | 13 | ## Limitations 14 | 15 | - It can only publish QoS 0 messages. It can subscribe at QoS 0 or QoS 1. 16 | - The maximum message size, including header, is **128 bytes** by default. This 17 | is configurable via `MQTT_MAX_PACKET_SIZE` in `PubSubClient.h`. Longer messages can also be sent with the `publish_P()` method. 18 | - The keepalive interval is set to 15 seconds by default. This is configurable 19 | via `MQTT_KEEPALIVE` in `PubSubClient.h`. 20 | - The client uses MQTT 3.1.1 by default. It can be changed to use MQTT 3.1 by 21 | changing value of `MQTT_VERSION` in `PubSubClient.h`. 22 | 23 | 24 | ## Compatible Hardware 25 | 26 | The library uses the Arduino Ethernet Client api for interacting with the 27 | underlying network hardware. This means it Just Works with a growing number of 28 | boards and shields, including: 29 | 30 | - Arduino Ethernet 31 | - Arduino Ethernet Shield 32 | - Arduino YUN – use the included `YunClient` in place of `EthernetClient`, and 33 | be sure to do a `Bridge.begin()` first 34 | - Arduino WiFi Shield - if you want to send packets > 90 bytes with this shield, 35 | enable the `MQTT_MAX_TRANSFER_SIZE` define in `PubSubClient.h`. 36 | - Sparkfun WiFly Shield – [library](https://github.com/dpslwk/WiFly) 37 | - TI CC3000 WiFi - [library](https://github.com/sparkfun/SFE_CC3000_Library) 38 | - Intel Galileo/Edison 39 | - ESP8266 40 | - ESP32 41 | 42 | The library cannot currently be used with hardware based on the ENC28J60 chip – 43 | such as the Nanode or the Nuelectronics Ethernet Shield. For those, there is an 44 | [alternative library](https://github.com/njh/NanodeMQTT) available. 45 | 46 | ## License 47 | 48 | This code is released under the MIT License. 49 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/Metro/src/Metro.cpp: -------------------------------------------------------------------------------- 1 | 2 | #if defined(ARDUINO) && ARDUINO >= 100 3 | #include "Arduino.h" 4 | #else 5 | #include "WProgram.h" 6 | #endif 7 | #include "Metro.h" 8 | 9 | 10 | Metro::Metro(unsigned long interval_millis) 11 | { 12 | this->autoreset = 0; 13 | interval(interval_millis); 14 | reset(); 15 | } 16 | 17 | // New creator so I can use either the original check behavior or benjamin.soelberg's 18 | // suggested one (see below). 19 | // autoreset = 0 is benjamin.soelberg's check behavior 20 | // autoreset != 0 is the original behavior 21 | 22 | Metro::Metro(unsigned long interval_millis, uint8_t autoreset) 23 | { 24 | this->autoreset = autoreset; // Fix by Paul Bouchier 25 | interval(interval_millis); 26 | reset(); 27 | } 28 | 29 | void Metro::interval(unsigned long interval_millis) 30 | { 31 | this->interval_millis = interval_millis; 32 | } 33 | 34 | // Benjamin.soelberg's check behavior: 35 | // When a check is true, add the interval to the internal counter. 36 | // This should guarantee a better overall stability. 37 | 38 | // Original check behavior: 39 | // When a check is true, add the interval to the current millis() counter. 40 | // This method can add a certain offset over time. 41 | 42 | char Metro::check() 43 | { 44 | if (millis() - this->previous_millis >= this->interval_millis) { 45 | // As suggested by benjamin.soelberg@gmail.com, the following line 46 | // this->previous_millis = millis(); 47 | // was changed to 48 | // this->previous_millis += this->interval_millis; 49 | 50 | // If the interval is set to 0 we revert to the original behavior 51 | if (this->interval_millis <= 0 || this->autoreset ) { 52 | this->previous_millis = millis(); 53 | } else { 54 | this->previous_millis += this->interval_millis; 55 | } 56 | 57 | return 1; 58 | } 59 | 60 | 61 | 62 | return 0; 63 | 64 | } 65 | 66 | unsigned long Metro::checkMillis(){ 67 | unsigned long startTime = this->previous_millis; 68 | unsigned long endTime = this->previous_millis + this->interval_millis; 69 | unsigned long currentTime = millis(); 70 | unsigned long timeRemaining = endTime - currentTime; 71 | 72 | return timeRemaining; 73 | 74 | } 75 | 76 | void Metro::reset() 77 | { 78 | 79 | this->previous_millis = millis(); 80 | 81 | } 82 | 83 | 84 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/pubsubclient/examples/mqtt_basic/mqtt_basic.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Basic MQTT example 3 | 4 | This sketch demonstrates the basic capabilities of the library. 5 | It connects to an MQTT server then: 6 | - publishes "hello world" to the topic "outTopic" 7 | - subscribes to the topic "inTopic", printing out any messages 8 | it receives. NB - it assumes the received payloads are strings not binary 9 | 10 | It will reconnect to the server if the connection is lost using a blocking 11 | reconnect function. See the 'mqtt_reconnect_nonblocking' example for how to 12 | achieve the same result without blocking the main loop. 13 | 14 | */ 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | // Update these with values suitable for your network. 21 | byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; 22 | IPAddress ip(172, 16, 0, 100); 23 | IPAddress server(172, 16, 0, 2); 24 | 25 | void callback(char* topic, byte* payload, unsigned int length) { 26 | Serial.print("Message arrived ["); 27 | Serial.print(topic); 28 | Serial.print("] "); 29 | for (int i=0;i 0: 29 | self.client.loop() 30 | time.sleep(0.5) 31 | i -= 1 32 | self.assertTrue(i > 0, "message receive timed-out") 33 | self.assertEqual(len(self.message_queue), 1, "unexpected number of messages received") 34 | msg = self.message_queue.pop(0) 35 | self.assertEqual(msg.mid, 0, "message id not 0") 36 | self.assertEqual(msg.topic, "outTopic", "message topic incorrect") 37 | self.assertEqual(msg.payload, "hello world") 38 | self.assertEqual(msg.qos, 0, "message qos not 0") 39 | self.assertEqual(msg.retain, False, "message retain flag incorrect") 40 | 41 | def test_publish(self): 42 | self.assertEqual(len(self.message_queue), 0, "message queue not empty") 43 | payload = "abcdefghij" 44 | self.client.publish("inTopic", payload) 45 | 46 | i = 30 47 | while len(self.message_queue) == 0 and i > 0: 48 | self.client.loop() 49 | time.sleep(0.5) 50 | i -= 1 51 | 52 | self.assertTrue(i > 0, "message receive timed-out") 53 | self.assertEqual(len(self.message_queue), 1, "unexpected number of messages received") 54 | msg = self.message_queue.pop(0) 55 | self.assertEqual(msg.mid, 0, "message id not 0") 56 | self.assertEqual(msg.topic, "outTopic", "message topic incorrect") 57 | self.assertEqual(msg.payload, payload) 58 | self.assertEqual(msg.qos, 0, "message qos not 0") 59 | self.assertEqual(msg.retain, False, "message retain flag incorrect") 60 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/QRCode/tests/BitBuffer.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * QR Code generator library (C++) 3 | * 4 | * Copyright (c) Project Nayuki 5 | * https://www.nayuki.io/page/qr-code-generator-library 6 | * 7 | * (MIT License) 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 9 | * this software and associated documentation files (the "Software"), to deal in 10 | * the Software without restriction, including without limitation the rights to 11 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 12 | * the Software, and to permit persons to whom the Software is furnished to do so, 13 | * subject to the following conditions: 14 | * - The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * - The Software is provided "as is", without warranty of any kind, express or 17 | * implied, including but not limited to the warranties of merchantability, 18 | * fitness for a particular purpose and noninfringement. In no event shall the 19 | * authors or copyright holders be liable for any claim, damages or other 20 | * liability, whether in an action of contract, tort or otherwise, arising from, 21 | * out of or in connection with the Software or the use or other dealings in the 22 | * Software. 23 | */ 24 | 25 | #pragma once 26 | 27 | #include 28 | #include 29 | #include "QrSegment.hpp" 30 | 31 | 32 | namespace qrcodegen { 33 | 34 | /* 35 | * An appendable sequence of bits. Bits are packed in big endian within a byte. 36 | */ 37 | class BitBuffer { 38 | 39 | /*---- Fields ----*/ 40 | private: 41 | 42 | std::vector data; 43 | int bitLength; 44 | 45 | 46 | 47 | /*---- Constructor ----*/ 48 | public: 49 | 50 | // Creates an empty bit buffer (length 0). 51 | BitBuffer(); 52 | 53 | 54 | 55 | /*---- Methods ----*/ 56 | public: 57 | 58 | // Returns the number of bits in the buffer, which is a non-negative value. 59 | int getBitLength() const; 60 | 61 | 62 | // Returns a copy of all bytes, padding up to the nearest byte. 63 | std::vector getBytes() const; 64 | 65 | 66 | // Appends the given number of bits of the given value to this sequence. 67 | // If 0 <= len <= 31, then this requires 0 <= val < 2^len. 68 | void appendBits(uint32_t val, int len); 69 | 70 | 71 | // Appends the data of the given segment to this bit buffer. 72 | void appendData(const QrSegment &seg); 73 | 74 | }; 75 | 76 | } 77 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/QRCode/tests/BitBuffer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * QR Code generator library (C++) 3 | * 4 | * Copyright (c) Project Nayuki 5 | * https://www.nayuki.io/page/qr-code-generator-library 6 | * 7 | * (MIT License) 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 9 | * this software and associated documentation files (the "Software"), to deal in 10 | * the Software without restriction, including without limitation the rights to 11 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 12 | * the Software, and to permit persons to whom the Software is furnished to do so, 13 | * subject to the following conditions: 14 | * - The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * - The Software is provided "as is", without warranty of any kind, express or 17 | * implied, including but not limited to the warranties of merchantability, 18 | * fitness for a particular purpose and noninfringement. In no event shall the 19 | * authors or copyright holders be liable for any claim, damages or other 20 | * liability, whether in an action of contract, tort or otherwise, arising from, 21 | * out of or in connection with the Software or the use or other dealings in the 22 | * Software. 23 | */ 24 | 25 | #include 26 | #include "BitBuffer.hpp" 27 | 28 | 29 | qrcodegen::BitBuffer::BitBuffer() : 30 | data(), 31 | bitLength(0) {} 32 | 33 | 34 | int qrcodegen::BitBuffer::getBitLength() const { 35 | return bitLength; 36 | } 37 | 38 | 39 | std::vector qrcodegen::BitBuffer::getBytes() const { 40 | return data; 41 | } 42 | 43 | 44 | void qrcodegen::BitBuffer::appendBits(uint32_t val, int len) { 45 | if (len < 0 || len > 32 || (len < 32 && (val >> len) != 0)) 46 | throw "Value out of range"; 47 | size_t newBitLen = bitLength + len; 48 | while (data.size() * 8 < newBitLen) 49 | data.push_back(0); 50 | for (int i = len - 1; i >= 0; i--, bitLength++) // Append bit by bit 51 | data.at(bitLength >> 3) |= ((val >> i) & 1) << (7 - (bitLength & 7)); 52 | } 53 | 54 | 55 | void qrcodegen::BitBuffer::appendData(const QrSegment &seg) { 56 | size_t newBitLen = bitLength + seg.bitLength; 57 | while (data.size() * 8 < newBitLen) 58 | data.push_back(0); 59 | for (int i = 0; i < seg.bitLength; i++, bitLength++) { // Append bit by bit 60 | int bit = (seg.data.at(i >> 3) >> (7 - (i & 7))) & 1; 61 | data.at(bitLength >> 3) |= bit << (7 - (bitLength & 7)); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/pubsubclient/CHANGES.txt: -------------------------------------------------------------------------------- 1 | 2.7 2 | * Fix remaining-length handling to prevent buffer overrun 3 | * Add large-payload API - beginPublish/write/publish/endPublish 4 | * Add yield call to improve reliability on ESP 5 | * Add Clean Session flag to connect options 6 | * Add ESP32 support for functional callback signature 7 | * Various other fixes 8 | 9 | 2.4 10 | * Add MQTT_SOCKET_TIMEOUT to prevent it blocking indefinitely 11 | whilst waiting for inbound data 12 | * Fixed return code when publishing >256 bytes 13 | 14 | 2.3 15 | * Add publish(topic,payload,retained) function 16 | 17 | 2.2 18 | * Change code layout to match Arduino Library reqs 19 | 20 | 2.1 21 | * Add MAX_TRANSFER_SIZE def to chunk messages if needed 22 | * Reject topic/payloads that exceed MQTT_MAX_PACKET_SIZE 23 | 24 | 2.0 25 | * Add (and default to) MQTT 3.1.1 support 26 | * Fix PROGMEM handling for Intel Galileo/ESP8266 27 | * Add overloaded constructors for convenience 28 | * Add chainable setters for server/callback/client/stream 29 | * Add state function to return connack return code 30 | 31 | 1.9 32 | * Do not split MQTT packets over multiple calls to _client->write() 33 | * API change: All constructors now require an instance of Client 34 | to be passed in. 35 | * Fixed example to match 1.8 api changes - dpslwk 36 | * Added username/password support - WilHall 37 | * Added publish_P - publishes messages from PROGMEM - jobytaffey 38 | 39 | 1.8 40 | * KeepAlive interval is configurable in PubSubClient.h 41 | * Maximum packet size is configurable in PubSubClient.h 42 | * API change: Return boolean rather than int from various functions 43 | * API change: Length parameter in message callback changed 44 | from int to unsigned int 45 | * Various internal tidy-ups around types 46 | 1.7 47 | * Improved keepalive handling 48 | * Updated to the Arduino-1.0 API 49 | 1.6 50 | * Added the ability to publish a retained message 51 | 52 | 1.5 53 | * Added default constructor 54 | * Fixed compile error when used with arduino-0021 or later 55 | 56 | 1.4 57 | * Fixed connection lost handling 58 | 59 | 1.3 60 | * Fixed packet reading bug in PubSubClient.readPacket 61 | 62 | 1.2 63 | * Fixed compile error when used with arduino-0016 or later 64 | 65 | 66 | 1.1 67 | * Reduced size of library 68 | * Added support for Will messages 69 | * Clarified licensing - see LICENSE.txt 70 | 71 | 72 | 1.0 73 | * Only Quality of Service (QOS) 0 messaging is supported 74 | * The maximum message size, including header, is 128 bytes 75 | * The keepalive interval is set to 30 seconds 76 | * No support for Will messages 77 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/QRCode/src/qrcode.h: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2017 Richard Moore 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | /** 26 | * Special thanks to Nayuki (https://www.nayuki.io/) from which this library was 27 | * heavily inspired and compared against. 28 | * 29 | * See: https://github.com/nayuki/QR-Code-generator/tree/master/cpp 30 | */ 31 | 32 | 33 | #ifndef __QRCODE_H_ 34 | #define __QRCODE_H_ 35 | 36 | #ifndef __cplusplus 37 | typedef unsigned char bool; 38 | static const bool false = 0; 39 | static const bool true = 1; 40 | #endif 41 | 42 | #include 43 | 44 | 45 | // QR Code Format Encoding 46 | #define MODE_NUMERIC 0 47 | #define MODE_ALPHANUMERIC 1 48 | #define MODE_BYTE 2 49 | 50 | 51 | // Error Correction Code Levels 52 | #define ECC_LOW 0 53 | #define ECC_MEDIUM 1 54 | #define ECC_QUARTILE 2 55 | #define ECC_HIGH 3 56 | 57 | 58 | // If set to non-zero, this library can ONLY produce QR codes at that version 59 | // This saves a lot of dynamic memory, as the codeword tables are skipped 60 | #ifndef LOCK_VERSION 61 | #define LOCK_VERSION 0 62 | #endif 63 | 64 | 65 | typedef struct QRCode { 66 | uint8_t version; 67 | uint8_t size; 68 | uint8_t ecc; 69 | uint8_t mode; 70 | uint8_t mask; 71 | uint8_t *modules; 72 | } QRCode; 73 | 74 | 75 | #ifdef __cplusplus 76 | extern "C"{ 77 | #endif /* __cplusplus */ 78 | 79 | 80 | 81 | uint16_t qrcode_getBufferSize(uint8_t version); 82 | 83 | int8_t qrcode_initText(QRCode *qrcode, uint8_t *modules, uint8_t version, uint8_t ecc, const char *data); 84 | int8_t qrcode_initBytes(QRCode *qrcode, uint8_t *modules, uint8_t version, uint8_t ecc, uint8_t *data, uint16_t length); 85 | 86 | bool qrcode_getModule(QRCode *qrcode, uint8_t x, uint8_t y); 87 | 88 | 89 | 90 | #ifdef __cplusplus 91 | } 92 | #endif /* __cplusplus */ 93 | 94 | 95 | #endif /* __QRCODE_H_ */ 96 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/QRCode/tests/run-tests.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "../src/qrcode.h" 5 | #include "QrCode.hpp" 6 | 7 | static uint32_t check(const qrcodegen::QrCode &nayuki, QRCode *ricmoo) { 8 | uint32_t wrong = 0; 9 | 10 | if (nayuki.size != ricmoo->size) { wrong += (1 << 20); } 11 | 12 | int border = 4; 13 | for (int y = -border; y < nayuki.size + border; y++) { 14 | for (int x = -border; x < nayuki.size + border; x++) { 15 | if (!!nayuki.getModule(x, y) != qrcode_getModule(ricmoo, x, y)) { 16 | wrong++; 17 | } 18 | } 19 | } 20 | 21 | return wrong; 22 | } 23 | 24 | int main() { 25 | std::clock_t t0, totalNayuki, totalRicMoo; 26 | 27 | int total = 0, passed = 0; 28 | for (char version = 1; version <= 40; version++) { 29 | if (LOCK_VERSION != 0 && LOCK_VERSION != version) { continue; } 30 | 31 | for (char ecc = 0; ecc < 4; ecc++) { 32 | const qrcodegen::QrCode::Ecc *errCorLvl; 33 | switch (ecc) { 34 | case 0: 35 | errCorLvl = &qrcodegen::QrCode::Ecc::LOW; 36 | break; 37 | case 1: 38 | errCorLvl = &qrcodegen::QrCode::Ecc::MEDIUM; 39 | break; 40 | case 2: 41 | errCorLvl = &qrcodegen::QrCode::Ecc::QUARTILE; 42 | break; 43 | case 3: 44 | errCorLvl = &qrcodegen::QrCode::Ecc::HIGH; 45 | break; 46 | } 47 | 48 | for (char tc = 0; tc < 3; tc++) { 49 | char *data; 50 | switch(tc) { 51 | case 0: 52 | data = (char*)"HELLO"; 53 | break; 54 | case 1: 55 | data = (char*)"Hello"; 56 | break; 57 | case 2: 58 | data = (char*)"1234"; 59 | break; 60 | } 61 | t0 = std::clock(); 62 | const qrcodegen::QrCode nayuki = qrcodegen::QrCode::encodeText(data, version, *errCorLvl); 63 | totalNayuki += std::clock() - t0; 64 | 65 | t0 = std::clock(); 66 | QRCode ricmoo; 67 | uint8_t ricmooBytes[qrcode_getBufferSize(version)]; 68 | qrcode_initText(&ricmoo, ricmooBytes, version, ecc, data); 69 | totalRicMoo += std::clock() - t0; 70 | 71 | uint32_t badModules = check(nayuki, &ricmoo); 72 | if (badModules) { 73 | printf("Failed test case: version=%d, ecc=%d, data=\"%s\", faliured=%d\n", version, ecc, data, badModules); 74 | } else { 75 | passed++; 76 | } 77 | 78 | total++; 79 | } 80 | } 81 | } 82 | 83 | printf("Tests complete: %d passed (out of %d)\n", passed, total); 84 | printf("Timing: Nayuki=%lu, RicMoo=%lu\n", totalNayuki, totalRicMoo); 85 | } 86 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/pubsubclient/tests/src/lib/IPAddress.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * MIT License: 4 | * Copyright (c) 2011 Adrian McEwen 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | * THE SOFTWARE. 22 | * 23 | * adrianm@mcqn.com 1/1/2011 24 | */ 25 | 26 | #ifndef IPAddress_h 27 | #define IPAddress_h 28 | 29 | 30 | // A class to make it easier to handle and pass around IP addresses 31 | 32 | class IPAddress { 33 | private: 34 | uint8_t _address[4]; // IPv4 address 35 | // Access the raw byte array containing the address. Because this returns a pointer 36 | // to the internal structure rather than a copy of the address this function should only 37 | // be used when you know that the usage of the returned uint8_t* will be transient and not 38 | // stored. 39 | uint8_t* raw_address() { return _address; }; 40 | 41 | public: 42 | // Constructors 43 | IPAddress(); 44 | IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet); 45 | IPAddress(uint32_t address); 46 | IPAddress(const uint8_t *address); 47 | 48 | // Overloaded cast operator to allow IPAddress objects to be used where a pointer 49 | // to a four-byte uint8_t array is expected 50 | operator uint32_t() { return *((uint32_t*)_address); }; 51 | bool operator==(const IPAddress& addr) { return (*((uint32_t*)_address)) == (*((uint32_t*)addr._address)); }; 52 | bool operator==(const uint8_t* addr); 53 | 54 | // Overloaded index operator to allow getting and setting individual octets of the address 55 | uint8_t operator[](int index) const { return _address[index]; }; 56 | uint8_t& operator[](int index) { return _address[index]; }; 57 | 58 | // Overloaded copy operators to allow initialisation of IPAddress objects from other types 59 | IPAddress& operator=(const uint8_t *address); 60 | IPAddress& operator=(uint32_t address); 61 | 62 | 63 | friend class EthernetClass; 64 | friend class UDP; 65 | friend class Client; 66 | friend class Server; 67 | friend class DhcpClass; 68 | friend class DNSClient; 69 | }; 70 | 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/pubsubclient/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 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/pubsubclient/examples/mqtt_esp8266/mqtt_esp8266.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Basic ESP8266 MQTT example 3 | This sketch demonstrates the capabilities of the pubsub library in combination 4 | with the ESP8266 board/library. 5 | It connects to an MQTT server then: 6 | - publishes "hello world" to the topic "outTopic" every two seconds 7 | - subscribes to the topic "inTopic", printing out any messages 8 | it receives. NB - it assumes the received payloads are strings not binary 9 | - If the first character of the topic "inTopic" is an 1, switch ON the ESP Led, 10 | else switch it off 11 | It will reconnect to the server if the connection is lost using a blocking 12 | reconnect function. See the 'mqtt_reconnect_nonblocking' example for how to 13 | achieve the same result without blocking the main loop. 14 | To install the ESP8266 board, (using Arduino 1.6.4+): 15 | - Add the following 3rd party board manager under "File -> Preferences -> Additional Boards Manager URLs": 16 | http://arduino.esp8266.com/stable/package_esp8266com_index.json 17 | - Open the "Tools -> Board -> Board Manager" and click install for the ESP8266" 18 | - Select your ESP8266 in "Tools -> Board" 19 | */ 20 | 21 | #include 22 | #include 23 | 24 | // Update these with values suitable for your network. 25 | 26 | const char* ssid = "........"; 27 | const char* password = "........"; 28 | const char* mqtt_server = "broker.mqtt-dashboard.com"; 29 | 30 | WiFiClient espClient; 31 | PubSubClient client(espClient); 32 | unsigned long lastMsg = 0; 33 | #define MSG_BUFFER_SIZE (50) 34 | char msg[MSG_BUFFER_SIZE]; 35 | int value = 0; 36 | 37 | void setup_wifi() { 38 | 39 | delay(10); 40 | // We start by connecting to a WiFi network 41 | Serial.println(); 42 | Serial.print("Connecting to "); 43 | Serial.println(ssid); 44 | 45 | WiFi.begin(ssid, password); 46 | 47 | while (WiFi.status() != WL_CONNECTED) { 48 | delay(500); 49 | Serial.print("."); 50 | } 51 | 52 | randomSeed(micros()); 53 | 54 | Serial.println(""); 55 | Serial.println("WiFi connected"); 56 | Serial.println("IP address: "); 57 | Serial.println(WiFi.localIP()); 58 | } 59 | 60 | void callback(char* topic, byte* payload, unsigned int length) { 61 | Serial.print("Message arrived ["); 62 | Serial.print(topic); 63 | Serial.print("] "); 64 | for (int i = 0; i < length; i++) { 65 | Serial.print((char)payload[i]); 66 | } 67 | Serial.println(); 68 | 69 | // Switch on the LED if an 1 was received as first character 70 | if ((char)payload[0] == '1') { 71 | digitalWrite(BUILTIN_LED, LOW); // Turn the LED on (Note that LOW is the voltage level 72 | // but actually the LED is on; this is because 73 | // it is active low on the ESP-01) 74 | } else { 75 | digitalWrite(BUILTIN_LED, HIGH); // Turn the LED off by making the voltage HIGH 76 | } 77 | 78 | } 79 | 80 | void reconnect() { 81 | // Loop until we're reconnected 82 | while (!client.connected()) { 83 | Serial.print("Attempting MQTT connection..."); 84 | // Create a random client ID 85 | String clientId = "ESP8266Client-"; 86 | clientId += String(random(0xffff), HEX); 87 | // Attempt to connect 88 | if (client.connect(clientId.c_str())) { 89 | Serial.println("connected"); 90 | // Once connected, publish an announcement... 91 | client.publish("outTopic", "hello world"); 92 | // ... and resubscribe 93 | client.subscribe("inTopic"); 94 | } else { 95 | Serial.print("failed, rc="); 96 | Serial.print(client.state()); 97 | Serial.println(" try again in 5 seconds"); 98 | // Wait 5 seconds before retrying 99 | delay(5000); 100 | } 101 | } 102 | } 103 | 104 | void setup() { 105 | pinMode(BUILTIN_LED, OUTPUT); // Initialize the BUILTIN_LED pin as an output 106 | Serial.begin(115200); 107 | setup_wifi(); 108 | client.setServer(mqtt_server, 1883); 109 | client.setCallback(callback); 110 | } 111 | 112 | void loop() { 113 | 114 | if (!client.connected()) { 115 | reconnect(); 116 | } 117 | client.loop(); 118 | 119 | unsigned long now = millis(); 120 | if (now - lastMsg > 2000) { 121 | lastMsg = now; 122 | ++value; 123 | snprintf (msg, MSG_BUFFER_SIZE, "hello world #%ld", value); 124 | Serial.print("Publish message: "); 125 | Serial.println(msg); 126 | client.publish("outTopic", msg); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /twitterScraper.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | import twitter 3 | import paho.mqtt.client as mqtt 4 | 5 | import time 6 | import json 7 | import sys 8 | import os 9 | from datetime import datetime, timezone 10 | 11 | import random 12 | from unidecode import unidecode 13 | 14 | import textwrap 15 | 16 | scriptPath = os.path.dirname(os.path.realpath(__file__)) + '/' 17 | 18 | 19 | 20 | #set ths to true to have the order of lines reversed. This value should match the one found in 21 | #the .ino project file. 22 | FLIPPED_PRINTING = True 23 | 24 | 25 | 26 | #set this to true to have the script run persistently and sleep until it needs to grab another tweet 27 | #set this to false if using this script via a cron type scheduled task 28 | RUN_LOOP = False 29 | 30 | #If using loop rather than cron type execution, this is the 31 | #time in seconds for loop to sleep before grabbing another 32 | #tweet (default: 3600 seconds which is 1 hour) 33 | LOOP_SLEEP_SECONDS = 3600 34 | 35 | 36 | 37 | #Twitter developer api keys (set these according to your own api keys) 38 | CONSUMER_KEY= '***********************' 39 | CONSUMER_SECRET= '***********************' 40 | ACCESS_TOKEN_KEY= '***********************' 41 | ACCESS_TOKEN_SECRET='***********************' 42 | 43 | 44 | 45 | 46 | #MQTT Broker details (set these according to your own setup) 47 | 48 | MQTT_HOST = "YOUR.MQTT.IP.HOST" 49 | MQTT_USER = '' #optional 50 | MQTT_PASS = '' #optional 51 | MQTT_PORT = 1883 52 | MQTT_TOPIC = '/your/mqtt/topic' 53 | 54 | TAGS_FILE = scriptPath + "twitterTags.txt" 55 | 56 | 57 | 58 | 59 | #convert utc to local datetime 60 | def utc_to_local(utc_dt): 61 | return utc_dt.replace(tzinfo=timezone.utc).astimezone(tz=None) 62 | 63 | #read and parse the tags file 64 | def readFile(filename): 65 | fp = open(filename,'r') 66 | tags = [] 67 | for line in fp: 68 | tags += [line.strip()] 69 | fp.close() 70 | return tags 71 | 72 | 73 | def main(): 74 | api = twitter.Api(consumer_key=CONSUMER_KEY, 75 | consumer_secret=CONSUMER_SECRET, 76 | access_token_key=ACCESS_TOKEN_KEY, 77 | access_token_secret=ACCESS_TOKEN_SECRET) 78 | 79 | 80 | #grab a hashtag from the tags file 81 | tags = readFile(TAGS_FILE) 82 | tag = tags[random.randrange(len(tags))] 83 | 84 | #generate the proper query depending on hashtag or @user 85 | query = '' 86 | if tag[0] == '#': 87 | query = 'q=-filter%3Aretweets%23' + tag[1:] 88 | elif tag[0] == '@': 89 | query = 'q=from%3A' + tag[1:] 90 | 91 | 92 | attemptsLeft = 3 93 | timeline = [] 94 | while(len(timeline) == 0 and attemptsLeft > 0): 95 | #grab a tweet from the api 96 | timeline = api.GetSearch(raw_query=query + "%20&result_type=recent&lang=en&count=1&tweet_mode=extended") 97 | if(len(timeline) == 0): 98 | print("twitter search failed - trying again in 5 seconds") 99 | time.sleep(5) 100 | 101 | if(len(timeline) == 0): 102 | return 103 | 104 | dictVersion = timeline[0].AsDict() 105 | 106 | 107 | # print(json.dumps(timeline[0]._json, sort_keys=True, indent=4)) #view raw twitter data 108 | 109 | #parse the tweet data 110 | text = unidecode(dictVersion['full_text']) 111 | name = unidecode(dictVersion["user"]["name"]) 112 | date = unidecode(dictVersion["created_at"]) 113 | 114 | #convert the timestamp to local time (comment these two lines to use utc) 115 | timeVal = utc_to_local(datetime.strptime(date, "%a %b %d %H:%M:%S %z %Y")) 116 | date = datetime.strftime(timeVal, "%a %b %d %H:%M:%S %Z %Y") 117 | 118 | 119 | #generate the wrapped text 120 | text = textwrap.fill(text, width=31) 121 | 122 | #if the text should be flipped for printing 123 | #(last line first) then do that now 124 | if(FLIPPED_PRINTING == True): 125 | lineList = text.split('\n') 126 | lineList.reverse() 127 | text = '\n'.join(lineList) 128 | 129 | 130 | #uncomment me to test without mqtt 131 | # exit() 132 | 133 | #connect to mqtt and send the tweet 134 | mqttClient = mqtt.Client() 135 | mqttClient.username_pw_set(MQTT_USER, MQTT_PASS) 136 | mqttClient.connect(MQTT_HOST, MQTT_PORT, 60) 137 | 138 | #handle mqtt differently depending on whether the text should be revered or not 139 | if(FLIPPED_PRINTING == True): 140 | mqttClient.publish(MQTT_TOPIC, text + '\n\n' + date +"\nUser: "+ name) 141 | else: 142 | mqttClient.publish(MQTT_TOPIC, "User: "+ name + '\n' + date + '\n\n' + text) 143 | 144 | 145 | 146 | 147 | 148 | if __name__ == '__main__': 149 | if(RUN_LOOP == True): 150 | while(True): 151 | main() 152 | time.sleep(LOOP_SLEEP_SECONDS) 153 | 154 | else: 155 | main() 156 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/QRCode/generate_table.py: -------------------------------------------------------------------------------- 1 | Data = [ 2 | ["1", "41", "25", "17", "34", "20", "14","27", "16", "11","17", "10", "7"], 3 | ["2", "77", "47", "32", "63", "38", "26", "48", "29", "20", "34", "20", "14"], 4 | ["3", "127", "77", "53", "101", "61", "42", "77", "47", "32", "58", "35", "24"], 5 | ["4", "187", "114", "78", "149", "90", "62", "111", "67", "46", "82", "50", "34"], 6 | ["5", "255", "154", "106", "202", "122", "84", "144", "87", "60", "106", "64", "44"], 7 | ["6", "322", "195", "134", "255", "154", "106", "178", "108", "74", "139", "84", "58"], 8 | ["7", "370", "224", "154", "293", "178", "122", "207", "125", "86", "154", "93", "64"], 9 | ["8", "461", "279", "192", "365", "221", "152", "259", "157", "108", "202", "122", "84"], 10 | ["9", "552", "335", "230", "432", "262", "180", "312", "189", "130", "235", "143", "98"], 11 | ["10", "652", "395", "271", "513", "311", "213", "364", "221", "151", "288", "174", "119"], 12 | ["11", "772", "468", "321", "604", "366", "251", "427", "259", "177", "331", "200", "137"], 13 | ["12", "883", "535", "367", "691", "419", "287", "489", "296", "203", "374", "227", "155"], 14 | ["13", "1022", "619", "425", "796", "483", "331", "580", "352", "241", "427", "259", "177"], 15 | ["14", "1101", "667", "458", "871", "528", "362", "621", "376", "258", "468", "283", "194"], 16 | ["15", "1250", "758", "520", "991", "600", "412", "703", "426", "292", "530", "321", "220"], 17 | ["16", "1408", "854", "586", "1082", "656", "450", "775", "470", "322", "602", "365", "250"], 18 | ["17", "1548", "938", "644", "1212", "734", "504", "876", "531", "364", "674", "408", "280"], 19 | ["18", "1725", "1046", "718", "1346", "816", "560", "948", "574", "394", "746", "452", "310"], 20 | ["19", "1903", "1153", "792", "1500", "909", "624", "1063", "644", "442", "813", "493", "338"], 21 | ["20", "2061", "1249", "858", "1600", "970", "666", "1159", "702", "482", "919", "557", "382"], 22 | ["21", "2232", "1352", "929", "1708", "1035", "711", "1224", "742", "509", "969", "587", "403"], 23 | ["22", "2409", "1460", "1003", "1872", "1134", "779", "1358", "823", "565", "1056", "640", "439"], 24 | ["23", "2620", "1588", "1091", "2059", "1248", "857", "1468", "890", "611", "1108", "672", "461"], 25 | ["24", "2812", "1704", "1171", "2188", "1326", "911", "1588", "963", "661", "1228", "744", "511"], 26 | ["25", "3057", "1853", "1273", "2395", "1451", "997", "1718", "1041", "715", "1286", "779", "535"], 27 | ["26", "3283", "1990", "1367", "2544", "1542", "1059", "1804", "1094", "751", "1425", "864", "593"], 28 | ["27", "3517", "2132", "1465", "2701", "1637", "1125", "1933", "1172", "805", "1501", "910", "625"], 29 | ["28", "3669", "2223", "1528", "2857", "1732", "1190", "2085", "1263", "868", "1581", "958", "658"], 30 | ["29", "3909", "2369", "1628", "3035", "1839", "1264", "2181", "1322", "908", "1677", "1016", "698"], 31 | ["30", "4158", "2520", "1732", "3289", "1994", "1370", "2358", "1429", "982", "1782", "1080", "742"], 32 | ["31", "4417", "2677", "1840", "3486", "2113", "1452", "2473", "1499", "1030", "1897", "1150", "790"], 33 | ["32", "4686", "2840", "1952", "3693", "2238", "1538", "2670", "1618", "1112", "2022", "1226", "842"], 34 | ["33", "4965", "3009", "2068", "3909", "2369", "1628", "2805", "1700", "1168", "2157", "1307", "898"], 35 | ["34", "5253", "3183", "2188", "4134", "2506", "1722", "2949", "1787", "1228", "2301", "1394", "958"], 36 | ["35", "5529", "3351", "2303", "4343", "2632", "1809", "3081", "1867", "1283", "2361", "1431", "983"], 37 | ["36", "5836", "3537", "2431", "4588", "2780", "1911", "3244", "1966", "1351", "2524", "1530", "1051"], 38 | ["37", "6153", "3729", "2563", "4775", "2894", "1989", "3417", "2071", "1423", "2625", "1591", "1093"], 39 | ["38", "6479", "3927", "2699", "5039", "3054", "2099", "3599", "2181", "1499", "2735", "1658", "1139"], 40 | ["39", "6743", "4087", "2809", "5313", "3220", "2213", "3791", "2298", "1579", "2927", "1774", "1219"], 41 | ["40", "7089", "4296", "2953", "5596", "3391", "2331", "3993", "2420", "1663", "3057", "1852", "1273"], 42 | ] 43 | Template = ''' 44 | %s 45 | %s 46 | LOW%s%s%s 47 | 48 | 49 | MEDIUM%s%s%s 50 | 51 | 52 | QUARTILE%s%s%s 53 | 54 | 55 | HIGH%s%s%s 56 | ''' 57 | 58 | for data in Data: 59 | data = data[:] 60 | size = 4 * int(data[0]) + 17 61 | data.insert(1, "%d x %d" % (size, size)) 62 | print Template % tuple(data) 63 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/pubsubclient/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 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/pubsubclient/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 | int test_subscribe_no_qos() { 15 | IT("subscribe without qos defaults to 0"); 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 subscribe[] = { 0x82,0xa,0x0,0x2,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x0 }; 27 | shimClient.expect(subscribe,12); 28 | byte suback[] = { 0x90,0x3,0x0,0x2,0x0 }; 29 | shimClient.respond(suback,5); 30 | 31 | rc = client.subscribe((char*)"topic"); 32 | IS_TRUE(rc); 33 | 34 | IS_FALSE(shimClient.error()); 35 | 36 | END_IT 37 | } 38 | 39 | int test_subscribe_qos_1() { 40 | IT("subscribes qos 1"); 41 | ShimClient shimClient; 42 | shimClient.setAllowConnect(true); 43 | 44 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 45 | shimClient.respond(connack,4); 46 | 47 | PubSubClient client(server, 1883, callback, shimClient); 48 | int rc = client.connect((char*)"client_test1"); 49 | IS_TRUE(rc); 50 | 51 | byte subscribe[] = { 0x82,0xa,0x0,0x2,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x1 }; 52 | shimClient.expect(subscribe,12); 53 | byte suback[] = { 0x90,0x3,0x0,0x2,0x1 }; 54 | shimClient.respond(suback,5); 55 | 56 | rc = client.subscribe((char*)"topic",1); 57 | IS_TRUE(rc); 58 | 59 | IS_FALSE(shimClient.error()); 60 | 61 | END_IT 62 | } 63 | 64 | int test_subscribe_not_connected() { 65 | IT("subscribe fails when not connected"); 66 | ShimClient shimClient; 67 | 68 | PubSubClient client(server, 1883, callback, shimClient); 69 | 70 | int rc = client.subscribe((char*)"topic"); 71 | IS_FALSE(rc); 72 | 73 | IS_FALSE(shimClient.error()); 74 | 75 | END_IT 76 | } 77 | 78 | int test_subscribe_invalid_qos() { 79 | IT("subscribe fails with invalid qos values"); 80 | ShimClient shimClient; 81 | shimClient.setAllowConnect(true); 82 | 83 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 84 | shimClient.respond(connack,4); 85 | 86 | PubSubClient client(server, 1883, callback, shimClient); 87 | int rc = client.connect((char*)"client_test1"); 88 | IS_TRUE(rc); 89 | 90 | rc = client.subscribe((char*)"topic",2); 91 | IS_FALSE(rc); 92 | rc = client.subscribe((char*)"topic",254); 93 | IS_FALSE(rc); 94 | 95 | IS_FALSE(shimClient.error()); 96 | 97 | END_IT 98 | } 99 | 100 | int test_subscribe_too_long() { 101 | IT("subscribe fails with too long topic"); 102 | ShimClient shimClient; 103 | shimClient.setAllowConnect(true); 104 | 105 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 106 | shimClient.respond(connack,4); 107 | 108 | PubSubClient client(server, 1883, callback, shimClient); 109 | int rc = client.connect((char*)"client_test1"); 110 | IS_TRUE(rc); 111 | 112 | // max length should be allowed 113 | // 0 1 2 3 4 5 6 7 8 9 0 1 2 114 | rc = client.subscribe((char*)"12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"); 115 | IS_TRUE(rc); 116 | 117 | // 0 1 2 3 4 5 6 7 8 9 0 1 2 118 | rc = client.subscribe((char*)"123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"); 119 | IS_FALSE(rc); 120 | 121 | IS_FALSE(shimClient.error()); 122 | 123 | END_IT 124 | } 125 | 126 | 127 | int test_unsubscribe() { 128 | IT("unsubscribes"); 129 | ShimClient shimClient; 130 | shimClient.setAllowConnect(true); 131 | 132 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 133 | shimClient.respond(connack,4); 134 | 135 | PubSubClient client(server, 1883, callback, shimClient); 136 | int rc = client.connect((char*)"client_test1"); 137 | IS_TRUE(rc); 138 | 139 | byte unsubscribe[] = { 0xA2,0x9,0x0,0x2,0x0,0x5,0x74,0x6f,0x70,0x69,0x63 }; 140 | shimClient.expect(unsubscribe,12); 141 | byte unsuback[] = { 0xB0,0x2,0x0,0x2 }; 142 | shimClient.respond(unsuback,4); 143 | 144 | rc = client.unsubscribe((char*)"topic"); 145 | IS_TRUE(rc); 146 | 147 | IS_FALSE(shimClient.error()); 148 | 149 | END_IT 150 | } 151 | 152 | int test_unsubscribe_not_connected() { 153 | IT("unsubscribe fails when not connected"); 154 | ShimClient shimClient; 155 | 156 | PubSubClient client(server, 1883, callback, shimClient); 157 | 158 | int rc = client.unsubscribe((char*)"topic"); 159 | IS_FALSE(rc); 160 | 161 | IS_FALSE(shimClient.error()); 162 | 163 | END_IT 164 | } 165 | 166 | int main() 167 | { 168 | SUITE("Subscribe"); 169 | test_subscribe_no_qos(); 170 | test_subscribe_qos_1(); 171 | test_subscribe_not_connected(); 172 | test_subscribe_invalid_qos(); 173 | test_subscribe_too_long(); 174 | test_unsubscribe(); 175 | test_unsubscribe_not_connected(); 176 | FINISH 177 | } 178 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/pubsubclient/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 - 1"); 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_retained_2() { 92 | IT("publishes retained - 2"); 93 | ShimClient shimClient; 94 | shimClient.setAllowConnect(true); 95 | 96 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 97 | shimClient.respond(connack,4); 98 | 99 | PubSubClient client(server, 1883, callback, shimClient); 100 | int rc = client.connect((char*)"client_test1"); 101 | IS_TRUE(rc); 102 | 103 | byte publish[] = {0x31,0xc,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,'A','B','C','D','E'}; 104 | shimClient.expect(publish,14); 105 | 106 | rc = client.publish((char*)"topic",(char*)"ABCDE",true); 107 | IS_TRUE(rc); 108 | 109 | IS_FALSE(shimClient.error()); 110 | 111 | END_IT 112 | } 113 | 114 | int test_publish_not_connected() { 115 | IT("publish fails when not connected"); 116 | ShimClient shimClient; 117 | 118 | PubSubClient client(server, 1883, callback, shimClient); 119 | 120 | int rc = client.publish((char*)"topic",(char*)"payload"); 121 | IS_FALSE(rc); 122 | 123 | IS_FALSE(shimClient.error()); 124 | 125 | END_IT 126 | } 127 | 128 | int test_publish_too_long() { 129 | IT("publish fails when topic/payload are too long"); 130 | ShimClient shimClient; 131 | shimClient.setAllowConnect(true); 132 | 133 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 134 | shimClient.respond(connack,4); 135 | 136 | PubSubClient client(server, 1883, callback, shimClient); 137 | int rc = client.connect((char*)"client_test1"); 138 | IS_TRUE(rc); 139 | 140 | // 0 1 2 3 4 5 6 7 8 9 0 1 2 141 | rc = client.publish((char*)"topic",(char*)"123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"); 142 | IS_FALSE(rc); 143 | 144 | IS_FALSE(shimClient.error()); 145 | 146 | END_IT 147 | } 148 | 149 | int test_publish_P() { 150 | IT("publishes using PROGMEM"); 151 | ShimClient shimClient; 152 | shimClient.setAllowConnect(true); 153 | 154 | byte payload[] = { 0x01,0x02,0x03,0x0,0x05 }; 155 | int length = 5; 156 | 157 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 158 | shimClient.respond(connack,4); 159 | 160 | PubSubClient client(server, 1883, callback, shimClient); 161 | int rc = client.connect((char*)"client_test1"); 162 | IS_TRUE(rc); 163 | 164 | byte publish[] = {0x31,0xc,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x1,0x2,0x3,0x0,0x5}; 165 | shimClient.expect(publish,14); 166 | 167 | rc = client.publish_P((char*)"topic",payload,length,true); 168 | IS_TRUE(rc); 169 | 170 | IS_FALSE(shimClient.error()); 171 | 172 | END_IT 173 | } 174 | 175 | 176 | 177 | 178 | int main() 179 | { 180 | SUITE("Publish"); 181 | test_publish(); 182 | test_publish_bytes(); 183 | test_publish_retained(); 184 | test_publish_retained_2(); 185 | test_publish_not_connected(); 186 | test_publish_too_long(); 187 | test_publish_P(); 188 | 189 | FINISH 190 | } 191 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/QRCode/tests/QrSegment.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * QR Code generator library (C++) 3 | * 4 | * Copyright (c) Project Nayuki 5 | * https://www.nayuki.io/page/qr-code-generator-library 6 | * 7 | * (MIT License) 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 9 | * this software and associated documentation files (the "Software"), to deal in 10 | * the Software without restriction, including without limitation the rights to 11 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 12 | * the Software, and to permit persons to whom the Software is furnished to do so, 13 | * subject to the following conditions: 14 | * - The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * - The Software is provided "as is", without warranty of any kind, express or 17 | * implied, including but not limited to the warranties of merchantability, 18 | * fitness for a particular purpose and noninfringement. In no event shall the 19 | * authors or copyright holders be liable for any claim, damages or other 20 | * liability, whether in an action of contract, tort or otherwise, arising from, 21 | * out of or in connection with the Software or the use or other dealings in the 22 | * Software. 23 | */ 24 | 25 | #pragma once 26 | 27 | #include 28 | #include 29 | 30 | 31 | namespace qrcodegen { 32 | 33 | /* 34 | * Represents a character string to be encoded in a QR Code symbol. Each segment has 35 | * a mode, and a sequence of characters that is already encoded as a sequence of bits. 36 | * Instances of this class are immutable. 37 | * This segment class imposes no length restrictions, but QR Codes have restrictions. 38 | * Even in the most favorable conditions, a QR Code can only hold 7089 characters of data. 39 | * Any segment longer than this is meaningless for the purpose of generating QR Codes. 40 | */ 41 | class QrSegment { 42 | 43 | /*---- Public helper enumeration ----*/ 44 | 45 | /* 46 | * The mode field of a segment. Immutable. Provides methods to retrieve closely related values. 47 | */ 48 | public: 49 | class Mode { 50 | 51 | /*-- Constants --*/ 52 | public: 53 | 54 | static const Mode NUMERIC; 55 | static const Mode ALPHANUMERIC; 56 | static const Mode BYTE; 57 | static const Mode KANJI; 58 | 59 | 60 | /*-- Fields --*/ 61 | 62 | /* (Package-private) An unsigned 4-bit integer value (range 0 to 15) representing the mode indicator bits for this mode object. */ 63 | public: 64 | const int modeBits; 65 | 66 | private: 67 | int numBitsCharCount[3]; 68 | 69 | 70 | /*-- Constructor --*/ 71 | 72 | private: 73 | Mode(int mode, int cc0, int cc1, int cc2); 74 | 75 | 76 | /*-- Method --*/ 77 | 78 | /* 79 | * (Package-private) Returns the bit width of the segment character count field for this mode object at the given version number. 80 | */ 81 | public: 82 | int numCharCountBits(int ver) const; 83 | 84 | }; 85 | 86 | 87 | 88 | /*---- Public static factory functions ----*/ 89 | public: 90 | 91 | /* 92 | * Returns a segment representing the given binary data encoded in byte mode. 93 | */ 94 | static QrSegment makeBytes(const std::vector &data); 95 | 96 | 97 | /* 98 | * Returns a segment representing the given string of decimal digits encoded in numeric mode. 99 | */ 100 | static QrSegment makeNumeric(const char *digits); 101 | 102 | 103 | /* 104 | * Returns a segment representing the given text string encoded in alphanumeric mode. The characters allowed are: 105 | * 0 to 9, A to Z (uppercase only), space, dollar, percent, asterisk, plus, hyphen, period, slash, colon. 106 | */ 107 | static QrSegment makeAlphanumeric(const char *text); 108 | 109 | 110 | /* 111 | * Returns a list of zero or more segments to represent the given text string. 112 | * The result may use various segment modes and switch modes to optimize the length of the bit stream. 113 | */ 114 | static std::vector makeSegments(const char *text); 115 | 116 | 117 | /*---- Public static helper functions ----*/ 118 | public: 119 | 120 | /* 121 | * Tests whether the given string can be encoded as a segment in alphanumeric mode. 122 | */ 123 | static bool isAlphanumeric(const char *text); 124 | 125 | 126 | /* 127 | * Tests whether the given string can be encoded as a segment in numeric mode. 128 | */ 129 | static bool isNumeric(const char *text); 130 | 131 | 132 | 133 | /*---- Instance fields ----*/ 134 | public: 135 | 136 | /* The mode indicator for this segment. */ 137 | const Mode mode; 138 | 139 | /* The length of this segment's unencoded data, measured in characters. Always zero or positive. */ 140 | const int numChars; 141 | 142 | /* The bits of this segment packed into a byte array in big endian. */ 143 | const std::vector data; 144 | 145 | /* The length of this segment's encoded data, measured in bits. Satisfies ceil(bitLength / 8) = data.size(). */ 146 | const int bitLength; 147 | 148 | 149 | /*---- Constructor ----*/ 150 | public: 151 | 152 | /* 153 | * Creates a new QR Code data segment with the given parameters and data. 154 | */ 155 | QrSegment(const Mode &md, int numCh, const std::vector &b, int bitLen); 156 | 157 | 158 | // Package-private helper function. 159 | static int getTotalBits(const std::vector &segs, int version); 160 | 161 | 162 | /*---- Private constant ----*/ 163 | private: 164 | 165 | /* Maps shifted ASCII codes to alphanumeric mode character codes. */ 166 | static const int8_t ALPHANUMERIC_ENCODING_TABLE[59]; 167 | 168 | }; 169 | 170 | } 171 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/pubsubclient/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 | #include 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 (takes 1 minute)"); 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 | if ( i == 15 || i == 31 || i == 47) { 36 | shimClient.expect(pingreq,2); 37 | shimClient.respond(pingresp,2); 38 | } 39 | rc = client.loop(); 40 | IS_TRUE(rc); 41 | } 42 | 43 | IS_FALSE(shimClient.error()); 44 | 45 | END_IT 46 | } 47 | 48 | int test_keepalive_pings_with_outbound_qos0() { 49 | IT("keeps a connection alive that only sends qos0 (takes 1 minute)"); 50 | 51 | ShimClient shimClient; 52 | shimClient.setAllowConnect(true); 53 | 54 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 55 | shimClient.respond(connack,4); 56 | 57 | PubSubClient client(server, 1883, callback, shimClient); 58 | int rc = client.connect((char*)"client_test1"); 59 | IS_TRUE(rc); 60 | 61 | byte publish[] = {0x30,0xe,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64}; 62 | 63 | for (int i = 0; i < 50; i++) { 64 | TRACE(i<<":"); 65 | shimClient.expect(publish,16); 66 | rc = client.publish((char*)"topic",(char*)"payload"); 67 | IS_TRUE(rc); 68 | IS_FALSE(shimClient.error()); 69 | sleep(1); 70 | if ( i == 15 || i == 31 || i == 47) { 71 | byte pingreq[] = { 0xC0,0x0 }; 72 | shimClient.expect(pingreq,2); 73 | byte pingresp[] = { 0xD0,0x0 }; 74 | shimClient.respond(pingresp,2); 75 | } 76 | rc = client.loop(); 77 | IS_TRUE(rc); 78 | IS_FALSE(shimClient.error()); 79 | } 80 | 81 | END_IT 82 | } 83 | 84 | int test_keepalive_pings_with_inbound_qos0() { 85 | IT("keeps a connection alive that only receives qos0 (takes 1 minute)"); 86 | 87 | ShimClient shimClient; 88 | shimClient.setAllowConnect(true); 89 | 90 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 91 | shimClient.respond(connack,4); 92 | 93 | PubSubClient client(server, 1883, callback, shimClient); 94 | int rc = client.connect((char*)"client_test1"); 95 | IS_TRUE(rc); 96 | 97 | byte publish[] = {0x30,0xe,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64}; 98 | 99 | for (int i = 0; i < 50; i++) { 100 | TRACE(i<<":"); 101 | sleep(1); 102 | if ( i == 15 || i == 31 || i == 47) { 103 | byte pingreq[] = { 0xC0,0x0 }; 104 | shimClient.expect(pingreq,2); 105 | byte pingresp[] = { 0xD0,0x0 }; 106 | shimClient.respond(pingresp,2); 107 | } 108 | shimClient.respond(publish,16); 109 | rc = client.loop(); 110 | IS_TRUE(rc); 111 | IS_FALSE(shimClient.error()); 112 | } 113 | 114 | END_IT 115 | } 116 | 117 | int test_keepalive_no_pings_inbound_qos1() { 118 | IT("does not send pings for connections with inbound qos1 (takes 1 minute)"); 119 | 120 | ShimClient shimClient; 121 | shimClient.setAllowConnect(true); 122 | 123 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 124 | shimClient.respond(connack,4); 125 | 126 | PubSubClient client(server, 1883, callback, shimClient); 127 | int rc = client.connect((char*)"client_test1"); 128 | IS_TRUE(rc); 129 | 130 | byte publish[] = {0x32,0x10,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x12,0x34,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64}; 131 | byte puback[] = {0x40,0x2,0x12,0x34}; 132 | 133 | for (int i = 0; i < 50; i++) { 134 | shimClient.respond(publish,18); 135 | shimClient.expect(puback,4); 136 | sleep(1); 137 | rc = client.loop(); 138 | IS_TRUE(rc); 139 | IS_FALSE(shimClient.error()); 140 | } 141 | 142 | END_IT 143 | } 144 | 145 | int test_keepalive_disconnects_hung() { 146 | IT("disconnects a hung connection (takes 30 seconds)"); 147 | 148 | ShimClient shimClient; 149 | shimClient.setAllowConnect(true); 150 | 151 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 152 | shimClient.respond(connack,4); 153 | 154 | PubSubClient client(server, 1883, callback, shimClient); 155 | int rc = client.connect((char*)"client_test1"); 156 | IS_TRUE(rc); 157 | 158 | byte pingreq[] = { 0xC0,0x0 }; 159 | shimClient.expect(pingreq,2); 160 | 161 | for (int i = 0; i < 32; i++) { 162 | sleep(1); 163 | rc = client.loop(); 164 | } 165 | IS_FALSE(rc); 166 | 167 | int state = client.state(); 168 | IS_TRUE(state == MQTT_CONNECTION_TIMEOUT); 169 | 170 | IS_FALSE(shimClient.error()); 171 | 172 | END_IT 173 | } 174 | 175 | int main() 176 | { 177 | SUITE("Keep-alive"); 178 | test_keepalive_pings_idle(); 179 | test_keepalive_pings_with_outbound_qos0(); 180 | test_keepalive_pings_with_inbound_qos0(); 181 | test_keepalive_no_pings_inbound_qos1(); 182 | test_keepalive_disconnects_hung(); 183 | 184 | FINISH 185 | } 186 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/pubsubclient/examples/mqtt_large_message/mqtt_large_message.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Long message ESP8266 MQTT example 3 | 4 | This sketch demonstrates sending arbitrarily large messages in combination 5 | with the ESP8266 board/library. 6 | 7 | It connects to an MQTT server then: 8 | - publishes "hello world" to the topic "outTopic" 9 | - subscribes to the topic "greenBottles/#", printing out any messages 10 | it receives. NB - it assumes the received payloads are strings not binary 11 | - If the sub-topic is a number, it publishes a "greenBottles/lyrics" message 12 | with a payload consisting of the lyrics to "10 green bottles", replacing 13 | 10 with the number given in the sub-topic. 14 | 15 | It will reconnect to the server if the connection is lost using a blocking 16 | reconnect function. See the 'mqtt_reconnect_nonblocking' example for how to 17 | achieve the same result without blocking the main loop. 18 | 19 | To install the ESP8266 board, (using Arduino 1.6.4+): 20 | - Add the following 3rd party board manager under "File -> Preferences -> Additional Boards Manager URLs": 21 | http://arduino.esp8266.com/stable/package_esp8266com_index.json 22 | - Open the "Tools -> Board -> Board Manager" and click install for the ESP8266" 23 | - Select your ESP8266 in "Tools -> Board" 24 | 25 | */ 26 | 27 | #include 28 | #include 29 | 30 | // Update these with values suitable for your network. 31 | 32 | const char* ssid = "........"; 33 | const char* password = "........"; 34 | const char* mqtt_server = "broker.mqtt-dashboard.com"; 35 | 36 | WiFiClient espClient; 37 | PubSubClient client(espClient); 38 | long lastMsg = 0; 39 | char msg[50]; 40 | int value = 0; 41 | 42 | void setup_wifi() { 43 | 44 | delay(10); 45 | // We start by connecting to a WiFi network 46 | Serial.println(); 47 | Serial.print("Connecting to "); 48 | Serial.println(ssid); 49 | 50 | WiFi.begin(ssid, password); 51 | 52 | while (WiFi.status() != WL_CONNECTED) { 53 | delay(500); 54 | Serial.print("."); 55 | } 56 | 57 | randomSeed(micros()); 58 | 59 | Serial.println(""); 60 | Serial.println("WiFi connected"); 61 | Serial.println("IP address: "); 62 | Serial.println(WiFi.localIP()); 63 | } 64 | 65 | void callback(char* topic, byte* payload, unsigned int length) { 66 | Serial.print("Message arrived ["); 67 | Serial.print(topic); 68 | Serial.print("] "); 69 | for (int i = 0; i < length; i++) { 70 | Serial.print((char)payload[i]); 71 | } 72 | Serial.println(); 73 | 74 | // Find out how many bottles we should generate lyrics for 75 | String topicStr(topic); 76 | int bottleCount = 0; // assume no bottles unless we correctly parse a value from the topic 77 | if (topicStr.indexOf('/') >= 0) { 78 | // The topic includes a '/', we'll try to read the number of bottles from just after that 79 | topicStr.remove(0, topicStr.indexOf('/')+1); 80 | // Now see if there's a number of bottles after the '/' 81 | bottleCount = topicStr.toInt(); 82 | } 83 | 84 | if (bottleCount > 0) { 85 | // Work out how big our resulting message will be 86 | int msgLen = 0; 87 | for (int i = bottleCount; i > 0; i--) { 88 | String numBottles(i); 89 | msgLen += 2*numBottles.length(); 90 | if (i == 1) { 91 | msgLen += 2*String(" green bottle, standing on the wall\n").length(); 92 | } else { 93 | msgLen += 2*String(" green bottles, standing on the wall\n").length(); 94 | } 95 | msgLen += String("And if one green bottle should accidentally fall\nThere'll be ").length(); 96 | switch (i) { 97 | case 1: 98 | msgLen += String("no green bottles, standing on the wall\n\n").length(); 99 | break; 100 | case 2: 101 | msgLen += String("1 green bottle, standing on the wall\n\n").length(); 102 | break; 103 | default: 104 | numBottles = i-1; 105 | msgLen += numBottles.length(); 106 | msgLen += String(" green bottles, standing on the wall\n\n").length(); 107 | break; 108 | }; 109 | } 110 | 111 | // Now we can start to publish the message 112 | client.beginPublish("greenBottles/lyrics", msgLen, false); 113 | for (int i = bottleCount; i > 0; i--) { 114 | for (int j = 0; j < 2; j++) { 115 | client.print(i); 116 | if (i == 1) { 117 | client.print(" green bottle, standing on the wall\n"); 118 | } else { 119 | client.print(" green bottles, standing on the wall\n"); 120 | } 121 | } 122 | client.print("And if one green bottle should accidentally fall\nThere'll be "); 123 | switch (i) { 124 | case 1: 125 | client.print("no green bottles, standing on the wall\n\n"); 126 | break; 127 | case 2: 128 | client.print("1 green bottle, standing on the wall\n\n"); 129 | break; 130 | default: 131 | client.print(i-1); 132 | client.print(" green bottles, standing on the wall\n\n"); 133 | break; 134 | }; 135 | } 136 | // Now we're done! 137 | client.endPublish(); 138 | } 139 | } 140 | 141 | void reconnect() { 142 | // Loop until we're reconnected 143 | while (!client.connected()) { 144 | Serial.print("Attempting MQTT connection..."); 145 | // Create a random client ID 146 | String clientId = "ESP8266Client-"; 147 | clientId += String(random(0xffff), HEX); 148 | // Attempt to connect 149 | if (client.connect(clientId.c_str())) { 150 | Serial.println("connected"); 151 | // Once connected, publish an announcement... 152 | client.publish("outTopic", "hello world"); 153 | // ... and resubscribe 154 | client.subscribe("greenBottles/#"); 155 | } else { 156 | Serial.print("failed, rc="); 157 | Serial.print(client.state()); 158 | Serial.println(" try again in 5 seconds"); 159 | // Wait 5 seconds before retrying 160 | delay(5000); 161 | } 162 | } 163 | } 164 | 165 | void setup() { 166 | pinMode(BUILTIN_LED, OUTPUT); // Initialize the BUILTIN_LED pin as an output 167 | Serial.begin(115200); 168 | setup_wifi(); 169 | client.setServer(mqtt_server, 1883); 170 | client.setCallback(callback); 171 | } 172 | 173 | void loop() { 174 | 175 | if (!client.connected()) { 176 | reconnect(); 177 | } 178 | client.loop(); 179 | } 180 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/pubsubclient/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 | 14 | class Workspace(object): 15 | 16 | def __init__(self): 17 | self.root_dir = os.getcwd() 18 | self.build_dir = os.path.join(self.root_dir, "tmpbin") 19 | self.log_dir = os.path.join(self.root_dir, "logs") 20 | self.tests_dir = os.path.join(self.root_dir, "testcases") 21 | self.examples_dir = os.path.join(self.root_dir, "../PubSubClient/examples") 22 | self.examples = [] 23 | self.tests = [] 24 | if not os.path.isdir("../PubSubClient"): 25 | raise Exception("Cannot find PubSubClient library") 26 | try: 27 | return __import__('ino') 28 | except ImportError: 29 | raise Exception("ino tool not installed") 30 | 31 | def init(self): 32 | if os.path.isdir(self.build_dir): 33 | shutil.rmtree(self.build_dir) 34 | os.mkdir(self.build_dir) 35 | if os.path.isdir(self.log_dir): 36 | shutil.rmtree(self.log_dir) 37 | os.mkdir(self.log_dir) 38 | 39 | os.chdir(self.build_dir) 40 | call(["ino", "init"]) 41 | 42 | shutil.copytree("../../PubSubClient", "lib/PubSubClient") 43 | 44 | filenames = [] 45 | for root, dirs, files in os.walk(self.examples_dir): 46 | filenames += [os.path.join(root, f) for f in files if f.endswith(".ino")] 47 | filenames.sort() 48 | for e in filenames: 49 | self.examples.append(Sketch(self, e)) 50 | 51 | filenames = [] 52 | for root, dirs, files in os.walk(self.tests_dir): 53 | filenames += [os.path.join(root, f) for f in files if f.endswith(".ino")] 54 | filenames.sort() 55 | for e in filenames: 56 | self.tests.append(Sketch(self, e)) 57 | 58 | def clean(self): 59 | shutil.rmtree(self.build_dir) 60 | 61 | 62 | class Sketch(object): 63 | def __init__(self, wksp, fn): 64 | self.w = wksp 65 | self.filename = fn 66 | self.basename = os.path.basename(self.filename) 67 | self.build_log = os.path.join(self.w.log_dir, "%s.log" % (os.path.basename(self.filename),)) 68 | self.build_err_log = os.path.join(self.w.log_dir, "%s.err.log" % (os.path.basename(self.filename),)) 69 | self.build_upload_log = os.path.join(self.w.log_dir, "%s.upload.log" % (os.path.basename(self.filename),)) 70 | 71 | def build(self): 72 | sys.stdout.write(" Build: ") 73 | sys.stdout.flush() 74 | 75 | # Copy sketch over, replacing IP addresses as necessary 76 | fin = open(self.filename, "r") 77 | lines = fin.readlines() 78 | fin.close() 79 | fout = open(os.path.join(self.w.build_dir, "src", "sketch.ino"), "w") 80 | for l in lines: 81 | if re.match(r"^byte server\[\] = {", l): 82 | fout.write("byte server[] = { %s };\n" % (settings.server_ip.replace(".", ", "),)) 83 | elif re.match(r"^byte ip\[\] = {", l): 84 | fout.write("byte ip[] = { %s };\n" % (settings.arduino_ip.replace(".", ", "),)) 85 | else: 86 | fout.write(l) 87 | fout.flush() 88 | fout.close() 89 | 90 | # Run build 91 | fout = open(self.build_log, "w") 92 | ferr = open(self.build_err_log, "w") 93 | rc = call(["ino", "build"], stdout=fout, stderr=ferr) 94 | fout.close() 95 | ferr.close() 96 | if rc == 0: 97 | sys.stdout.write("pass") 98 | sys.stdout.write("\n") 99 | return True 100 | else: 101 | sys.stdout.write("fail") 102 | sys.stdout.write("\n") 103 | with open(self.build_err_log) as f: 104 | for line in f: 105 | print(" " + line) 106 | return False 107 | 108 | def upload(self): 109 | sys.stdout.write(" Upload: ") 110 | sys.stdout.flush() 111 | fout = open(self.build_upload_log, "w") 112 | rc = call(["ino", "upload"], stdout=fout, stderr=fout) 113 | fout.close() 114 | if rc == 0: 115 | sys.stdout.write("pass") 116 | sys.stdout.write("\n") 117 | return True 118 | else: 119 | sys.stdout.write("fail") 120 | sys.stdout.write("\n") 121 | with open(self.build_upload_log) as f: 122 | for line in f: 123 | print(" " + line) 124 | return False 125 | 126 | def test(self): 127 | # import the matching test case, if it exists 128 | try: 129 | basename = os.path.basename(self.filename)[:-4] 130 | i = importlib.import_module("testcases." + basename) 131 | except: 132 | sys.stdout.write(" Test: no tests found") 133 | sys.stdout.write("\n") 134 | return 135 | c = getattr(i, basename) 136 | 137 | testmethods = [m for m in dir(c) if m.startswith("test_")] 138 | testmethods.sort() 139 | tests = [] 140 | for m in testmethods: 141 | tests.append(c(m)) 142 | 143 | result = unittest.TestResult() 144 | c.setUpClass() 145 | if self.upload(): 146 | sys.stdout.write(" Test: ") 147 | sys.stdout.flush() 148 | for t in tests: 149 | t.run(result) 150 | print(str(result.testsRun - len(result.failures) - len(result.errors)) + "/" + str(result.testsRun)) 151 | if not result.wasSuccessful(): 152 | if len(result.failures) > 0: 153 | for f in result.failures: 154 | print("-- " + str(f[0])) 155 | print(f[1]) 156 | if len(result.errors) > 0: 157 | print(" Errors:") 158 | for f in result.errors: 159 | print("-- " + str(f[0])) 160 | print(f[1]) 161 | c.tearDownClass() 162 | 163 | 164 | if __name__ == '__main__': 165 | run_tests = True 166 | 167 | w = Workspace() 168 | w.init() 169 | 170 | for e in w.examples: 171 | print("--------------------------------------") 172 | print("[" + e.basename + "]") 173 | if e.build() and run_tests: 174 | e.test() 175 | for e in w.tests: 176 | print("--------------------------------------") 177 | print("[" + e.basename + "]") 178 | if e.build() and run_tests: 179 | e.test() 180 | 181 | w.clean() 182 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/QRCode/tests/QrSegment.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * QR Code generator library (C++) 3 | * 4 | * Copyright (c) Project Nayuki 5 | * https://www.nayuki.io/page/qr-code-generator-library 6 | * 7 | * (MIT License) 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 9 | * this software and associated documentation files (the "Software"), to deal in 10 | * the Software without restriction, including without limitation the rights to 11 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 12 | * the Software, and to permit persons to whom the Software is furnished to do so, 13 | * subject to the following conditions: 14 | * - The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * - The Software is provided "as is", without warranty of any kind, express or 17 | * implied, including but not limited to the warranties of merchantability, 18 | * fitness for a particular purpose and noninfringement. In no event shall the 19 | * authors or copyright holders be liable for any claim, damages or other 20 | * liability, whether in an action of contract, tort or otherwise, arising from, 21 | * out of or in connection with the Software or the use or other dealings in the 22 | * Software. 23 | */ 24 | 25 | #include 26 | #include "BitBuffer.hpp" 27 | #include "QrSegment.hpp" 28 | 29 | 30 | qrcodegen::QrSegment::Mode::Mode(int mode, int cc0, int cc1, int cc2) : 31 | modeBits(mode) { 32 | numBitsCharCount[0] = cc0; 33 | numBitsCharCount[1] = cc1; 34 | numBitsCharCount[2] = cc2; 35 | } 36 | 37 | 38 | int qrcodegen::QrSegment::Mode::numCharCountBits(int ver) const { 39 | if ( 1 <= ver && ver <= 9) return numBitsCharCount[0]; 40 | else if (10 <= ver && ver <= 26) return numBitsCharCount[1]; 41 | else if (27 <= ver && ver <= 40) return numBitsCharCount[2]; 42 | else throw "Version number out of range"; 43 | } 44 | 45 | 46 | const qrcodegen::QrSegment::Mode qrcodegen::QrSegment::Mode::NUMERIC (0x1, 10, 12, 14); 47 | const qrcodegen::QrSegment::Mode qrcodegen::QrSegment::Mode::ALPHANUMERIC(0x2, 9, 11, 13); 48 | const qrcodegen::QrSegment::Mode qrcodegen::QrSegment::Mode::BYTE (0x4, 8, 16, 16); 49 | const qrcodegen::QrSegment::Mode qrcodegen::QrSegment::Mode::KANJI (0x8, 8, 10, 12); 50 | 51 | 52 | 53 | qrcodegen::QrSegment qrcodegen::QrSegment::makeBytes(const std::vector &data) { 54 | return QrSegment(Mode::BYTE, data.size(), data, data.size() * 8); 55 | } 56 | 57 | 58 | qrcodegen::QrSegment qrcodegen::QrSegment::makeNumeric(const char *digits) { 59 | BitBuffer bb; 60 | int accumData = 0; 61 | int accumCount = 0; 62 | int charCount = 0; 63 | for (; *digits != '\0'; digits++, charCount++) { 64 | char c = *digits; 65 | if (c < '0' || c > '9') 66 | throw "String contains non-numeric characters"; 67 | accumData = accumData * 10 + (c - '0'); 68 | accumCount++; 69 | if (accumCount == 3) { 70 | bb.appendBits(accumData, 10); 71 | accumData = 0; 72 | accumCount = 0; 73 | } 74 | } 75 | if (accumCount > 0) // 1 or 2 digits remaining 76 | bb.appendBits(accumData, accumCount * 3 + 1); 77 | return QrSegment(Mode::NUMERIC, charCount, bb.getBytes(), bb.getBitLength()); 78 | } 79 | 80 | 81 | qrcodegen::QrSegment qrcodegen::QrSegment::makeAlphanumeric(const char *text) { 82 | BitBuffer bb; 83 | int accumData = 0; 84 | int accumCount = 0; 85 | int charCount = 0; 86 | for (; *text != '\0'; text++, charCount++) { 87 | char c = *text; 88 | if (c < ' ' || c > 'Z') 89 | throw "String contains unencodable characters in alphanumeric mode"; 90 | accumData = accumData * 45 + ALPHANUMERIC_ENCODING_TABLE[c - ' ']; 91 | accumCount++; 92 | if (accumCount == 2) { 93 | bb.appendBits(accumData, 11); 94 | accumData = 0; 95 | accumCount = 0; 96 | } 97 | } 98 | if (accumCount > 0) // 1 character remaining 99 | bb.appendBits(accumData, 6); 100 | return QrSegment(Mode::ALPHANUMERIC, charCount, bb.getBytes(), bb.getBitLength()); 101 | } 102 | 103 | 104 | std::vector qrcodegen::QrSegment::makeSegments(const char *text) { 105 | // Select the most efficient segment encoding automatically 106 | std::vector result; 107 | if (*text == '\0'); // Leave the vector empty 108 | else if (QrSegment::isNumeric(text)) 109 | result.push_back(QrSegment::makeNumeric(text)); 110 | else if (QrSegment::isAlphanumeric(text)) 111 | result.push_back(QrSegment::makeAlphanumeric(text)); 112 | else { 113 | std::vector bytes; 114 | for (; *text != '\0'; text++) 115 | bytes.push_back(static_cast(*text)); 116 | result.push_back(QrSegment::makeBytes(bytes)); 117 | } 118 | return result; 119 | } 120 | 121 | 122 | qrcodegen::QrSegment::QrSegment(const Mode &md, int numCh, const std::vector &b, int bitLen) : 123 | mode(md), 124 | numChars(numCh), 125 | data(b), 126 | bitLength(bitLen) { 127 | if (numCh < 0 || bitLen < 0 || b.size() != static_cast((bitLen + 7) / 8)) 128 | throw "Invalid value"; 129 | } 130 | 131 | 132 | int qrcodegen::QrSegment::getTotalBits(const std::vector &segs, int version) { 133 | if (version < 1 || version > 40) 134 | throw "Version number out of range"; 135 | int result = 0; 136 | for (size_t i = 0; i < segs.size(); i++) { 137 | const QrSegment &seg(segs.at(i)); 138 | int ccbits = seg.mode.numCharCountBits(version); 139 | // Fail if segment length value doesn't fit in the length field's bit-width 140 | if (seg.numChars >= (1 << ccbits)) 141 | return -1; 142 | result += 4 + ccbits + seg.bitLength; 143 | } 144 | return result; 145 | } 146 | 147 | 148 | bool qrcodegen::QrSegment::isAlphanumeric(const char *text) { 149 | for (; *text != '\0'; text++) { 150 | char c = *text; 151 | if (c < ' ' || c > 'Z' || ALPHANUMERIC_ENCODING_TABLE[c - ' '] == -1) 152 | return false; 153 | } 154 | return true; 155 | } 156 | 157 | 158 | bool qrcodegen::QrSegment::isNumeric(const char *text) { 159 | for (; *text != '\0'; text++) { 160 | char c = *text; 161 | if (c < '0' || c > '9') 162 | return false; 163 | } 164 | return true; 165 | } 166 | 167 | 168 | const int8_t qrcodegen::QrSegment::ALPHANUMERIC_ENCODING_TABLE[59] = { 169 | // SP, !, ", #, $, %, &, ', (, ), *, +, ,, -, ., /, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, :, ;, <, =, >, ?, @, // ASCII codes 32 to 64 170 | 36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1, -1, // Array indices 0 to 32 171 | 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, // Array indices 33 to 58 172 | // A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, // ASCII codes 65 to 90 173 | }; 174 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/pubsubclient/src/PubSubClient.h: -------------------------------------------------------------------------------- 1 | /* 2 | PubSubClient.h - A simple client for MQTT. 3 | Nick O'Leary 4 | http://knolleary.net 5 | */ 6 | 7 | #ifndef PubSubClient_h 8 | #define PubSubClient_h 9 | 10 | #include 11 | #include "IPAddress.h" 12 | #include "Client.h" 13 | #include "Stream.h" 14 | 15 | #define MQTT_VERSION_3_1 3 16 | #define MQTT_VERSION_3_1_1 4 17 | 18 | // MQTT_VERSION : Pick the version 19 | //#define MQTT_VERSION MQTT_VERSION_3_1 20 | #ifndef MQTT_VERSION 21 | #define MQTT_VERSION MQTT_VERSION_3_1_1 22 | #endif 23 | 24 | // MQTT_MAX_PACKET_SIZE : Maximum packet size 25 | #ifndef MQTT_MAX_PACKET_SIZE 26 | #define MQTT_MAX_PACKET_SIZE 512 27 | #endif 28 | 29 | // MQTT_KEEPALIVE : keepAlive interval in Seconds 30 | #ifndef MQTT_KEEPALIVE 31 | #define MQTT_KEEPALIVE 15 32 | #endif 33 | 34 | // MQTT_SOCKET_TIMEOUT: socket timeout interval in Seconds 35 | #ifndef MQTT_SOCKET_TIMEOUT 36 | #define MQTT_SOCKET_TIMEOUT 15 37 | #endif 38 | 39 | // MQTT_MAX_TRANSFER_SIZE : limit how much data is passed to the network client 40 | // in each write call. Needed for the Arduino Wifi Shield. Leave undefined to 41 | // pass the entire MQTT packet in each write call. 42 | //#define MQTT_MAX_TRANSFER_SIZE 80 43 | 44 | // Possible values for client.state() 45 | #define MQTT_CONNECTION_TIMEOUT -4 46 | #define MQTT_CONNECTION_LOST -3 47 | #define MQTT_CONNECT_FAILED -2 48 | #define MQTT_DISCONNECTED -1 49 | #define MQTT_CONNECTED 0 50 | #define MQTT_CONNECT_BAD_PROTOCOL 1 51 | #define MQTT_CONNECT_BAD_CLIENT_ID 2 52 | #define MQTT_CONNECT_UNAVAILABLE 3 53 | #define MQTT_CONNECT_BAD_CREDENTIALS 4 54 | #define MQTT_CONNECT_UNAUTHORIZED 5 55 | 56 | #define MQTTCONNECT 1 << 4 // Client request to connect to Server 57 | #define MQTTCONNACK 2 << 4 // Connect Acknowledgment 58 | #define MQTTPUBLISH 3 << 4 // Publish message 59 | #define MQTTPUBACK 4 << 4 // Publish Acknowledgment 60 | #define MQTTPUBREC 5 << 4 // Publish Received (assured delivery part 1) 61 | #define MQTTPUBREL 6 << 4 // Publish Release (assured delivery part 2) 62 | #define MQTTPUBCOMP 7 << 4 // Publish Complete (assured delivery part 3) 63 | #define MQTTSUBSCRIBE 8 << 4 // Client Subscribe request 64 | #define MQTTSUBACK 9 << 4 // Subscribe Acknowledgment 65 | #define MQTTUNSUBSCRIBE 10 << 4 // Client Unsubscribe request 66 | #define MQTTUNSUBACK 11 << 4 // Unsubscribe Acknowledgment 67 | #define MQTTPINGREQ 12 << 4 // PING Request 68 | #define MQTTPINGRESP 13 << 4 // PING Response 69 | #define MQTTDISCONNECT 14 << 4 // Client is Disconnecting 70 | #define MQTTReserved 15 << 4 // Reserved 71 | 72 | #define MQTTQOS0 (0 << 1) 73 | #define MQTTQOS1 (1 << 1) 74 | #define MQTTQOS2 (2 << 1) 75 | 76 | // Maximum size of fixed header and variable length size header 77 | #define MQTT_MAX_HEADER_SIZE 5 78 | 79 | #if defined(ESP8266) || defined(ESP32) 80 | #include 81 | #define MQTT_CALLBACK_SIGNATURE std::function callback 82 | #else 83 | #define MQTT_CALLBACK_SIGNATURE void (*callback)(char*, uint8_t*, unsigned int) 84 | #endif 85 | 86 | #define CHECK_STRING_LENGTH(l,s) if (l+2+strlen(s) > MQTT_MAX_PACKET_SIZE) {_client->stop();return false;} 87 | 88 | class PubSubClient : public Print { 89 | private: 90 | Client* _client; 91 | uint8_t buffer[MQTT_MAX_PACKET_SIZE]; 92 | uint16_t nextMsgId; 93 | unsigned long lastOutActivity; 94 | unsigned long lastInActivity; 95 | bool pingOutstanding; 96 | MQTT_CALLBACK_SIGNATURE; 97 | uint32_t readPacket(uint8_t*); 98 | boolean readByte(uint8_t * result); 99 | boolean readByte(uint8_t * result, uint16_t * index); 100 | boolean write(uint8_t header, uint8_t* buf, uint16_t length); 101 | uint16_t writeString(const char* string, uint8_t* buf, uint16_t pos); 102 | // Build up the header ready to send 103 | // Returns the size of the header 104 | // Note: the header is built at the end of the first MQTT_MAX_HEADER_SIZE bytes, so will start 105 | // (MQTT_MAX_HEADER_SIZE - ) bytes into the buffer 106 | size_t buildHeader(uint8_t header, uint8_t* buf, uint16_t length); 107 | IPAddress ip; 108 | const char* domain; 109 | uint16_t port; 110 | Stream* stream; 111 | int _state; 112 | public: 113 | PubSubClient(); 114 | PubSubClient(Client& client); 115 | PubSubClient(IPAddress, uint16_t, Client& client); 116 | PubSubClient(IPAddress, uint16_t, Client& client, Stream&); 117 | PubSubClient(IPAddress, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client); 118 | PubSubClient(IPAddress, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client, Stream&); 119 | PubSubClient(uint8_t *, uint16_t, Client& client); 120 | PubSubClient(uint8_t *, uint16_t, Client& client, Stream&); 121 | PubSubClient(uint8_t *, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client); 122 | PubSubClient(uint8_t *, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client, Stream&); 123 | PubSubClient(const char*, uint16_t, Client& client); 124 | PubSubClient(const char*, uint16_t, Client& client, Stream&); 125 | PubSubClient(const char*, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client); 126 | PubSubClient(const char*, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client, Stream&); 127 | 128 | PubSubClient& setServer(IPAddress ip, uint16_t port); 129 | PubSubClient& setServer(uint8_t * ip, uint16_t port); 130 | PubSubClient& setServer(const char * domain, uint16_t port); 131 | PubSubClient& setCallback(MQTT_CALLBACK_SIGNATURE); 132 | PubSubClient& setClient(Client& client); 133 | PubSubClient& setStream(Stream& stream); 134 | 135 | boolean connect(const char* id); 136 | boolean connect(const char* id, const char* user, const char* pass); 137 | boolean connect(const char* id, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage); 138 | boolean connect(const char* id, const char* user, const char* pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage); 139 | boolean connect(const char* id, const char* user, const char* pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage, boolean cleanSession); 140 | void disconnect(); 141 | boolean publish(const char* topic, const char* payload); 142 | boolean publish(const char* topic, const char* payload, boolean retained); 143 | boolean publish(const char* topic, const uint8_t * payload, unsigned int plength); 144 | boolean publish(const char* topic, const uint8_t * payload, unsigned int plength, boolean retained); 145 | boolean publish_P(const char* topic, const char* payload, boolean retained); 146 | boolean publish_P(const char* topic, const uint8_t * payload, unsigned int plength, boolean retained); 147 | // Start to publish a message. 148 | // This API: 149 | // beginPublish(...) 150 | // one or more calls to write(...) 151 | // endPublish() 152 | // Allows for arbitrarily large payloads to be sent without them having to be copied into 153 | // a new buffer and held in memory at one time 154 | // Returns 1 if the message was started successfully, 0 if there was an error 155 | boolean beginPublish(const char* topic, unsigned int plength, boolean retained); 156 | // Finish off this publish message (started with beginPublish) 157 | // Returns 1 if the packet was sent successfully, 0 if there was an error 158 | int endPublish(); 159 | // Write a single byte of payload (only to be used with beginPublish/endPublish) 160 | virtual size_t write(uint8_t); 161 | // Write size bytes from buffer into the payload (only to be used with beginPublish/endPublish) 162 | // Returns the number of bytes written 163 | virtual size_t write(const uint8_t *buffer, size_t size); 164 | boolean subscribe(const char* topic); 165 | boolean subscribe(const char* topic, uint8_t qos); 166 | boolean unsubscribe(const char* topic); 167 | boolean loop(); 168 | boolean connected(); 169 | int state(); 170 | }; 171 | 172 | 173 | #endif 174 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/pubsubclient/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 | int 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 | int 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_drop_invalid_remaining_length_message() { 164 | IT("drops invalid remaining length message"); 165 | reset_callback(); 166 | 167 | ShimClient shimClient; 168 | shimClient.setAllowConnect(true); 169 | 170 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 171 | shimClient.respond(connack,4); 172 | 173 | PubSubClient client(server, 1883, callback, shimClient); 174 | int rc = client.connect((char*)"client_test1"); 175 | IS_TRUE(rc); 176 | 177 | byte publish[] = {0x30,0x92,0x92,0x92,0x92,0x01,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64}; 178 | shimClient.respond(publish,20); 179 | 180 | rc = client.loop(); 181 | 182 | IS_FALSE(rc); 183 | 184 | IS_FALSE(callback_called); 185 | 186 | IS_FALSE(shimClient.error()); 187 | 188 | END_IT 189 | } 190 | 191 | 192 | int test_receive_oversized_stream_message() { 193 | IT("receive an oversized streamed message"); 194 | reset_callback(); 195 | 196 | Stream stream; 197 | 198 | ShimClient shimClient; 199 | shimClient.setAllowConnect(true); 200 | 201 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 202 | shimClient.respond(connack,4); 203 | 204 | PubSubClient client(server, 1883, callback, shimClient, stream); 205 | int rc = client.connect((char*)"client_test1"); 206 | IS_TRUE(rc); 207 | 208 | int length = MQTT_MAX_PACKET_SIZE+1; 209 | byte publish[] = {0x30,length-2,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64}; 210 | 211 | byte bigPublish[length]; 212 | memset(bigPublish,'A',length); 213 | bigPublish[length] = 'B'; 214 | memcpy(bigPublish,publish,16); 215 | 216 | shimClient.respond(bigPublish,length); 217 | stream.expect(bigPublish+9,length-9); 218 | 219 | rc = client.loop(); 220 | 221 | IS_TRUE(rc); 222 | 223 | IS_TRUE(callback_called); 224 | IS_TRUE(strcmp(lastTopic,"topic")==0); 225 | IS_TRUE(lastLength == MQTT_MAX_PACKET_SIZE-9); 226 | 227 | IS_FALSE(stream.error()); 228 | IS_FALSE(shimClient.error()); 229 | 230 | END_IT 231 | } 232 | 233 | int test_receive_qos1() { 234 | IT("receives a qos1 message"); 235 | reset_callback(); 236 | 237 | ShimClient shimClient; 238 | shimClient.setAllowConnect(true); 239 | 240 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 241 | shimClient.respond(connack,4); 242 | 243 | PubSubClient client(server, 1883, callback, shimClient); 244 | int rc = client.connect((char*)"client_test1"); 245 | IS_TRUE(rc); 246 | 247 | byte publish[] = {0x32,0x10,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x12,0x34,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64}; 248 | shimClient.respond(publish,18); 249 | 250 | byte puback[] = {0x40,0x2,0x12,0x34}; 251 | shimClient.expect(puback,4); 252 | 253 | rc = client.loop(); 254 | 255 | IS_TRUE(rc); 256 | 257 | IS_TRUE(callback_called); 258 | IS_TRUE(strcmp(lastTopic,"topic")==0); 259 | IS_TRUE(memcmp(lastPayload,"payload",7)==0); 260 | IS_TRUE(lastLength == 7); 261 | 262 | IS_FALSE(shimClient.error()); 263 | 264 | END_IT 265 | } 266 | 267 | int main() 268 | { 269 | SUITE("Receive"); 270 | test_receive_callback(); 271 | test_receive_stream(); 272 | test_receive_max_sized_message(); 273 | test_drop_invalid_remaining_length_message(); 274 | test_receive_oversized_message(); 275 | test_receive_oversized_stream_message(); 276 | test_receive_qos1(); 277 | 278 | FINISH 279 | } 280 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/ESPHelper_Utils/ESPHelper_base.h: -------------------------------------------------------------------------------- 1 | #ifndef ESPHELPER_BASE 2 | #define ESPHELPER_BASE 3 | 4 | #include "ESPHelper.h" 5 | #include 6 | #include "ESPHelperFS.h" 7 | #include "ESPHelperWebConfig.h" 8 | 9 | 10 | 11 | 12 | //setup macros for time 13 | #define SECOND 1000L 14 | #define MINUTE SECOND * 60L 15 | #define HOUR MINUTE * 60L 16 | 17 | #define NETWORK_HOSTNAME "New-ESP" 18 | const char* HOSTNAME = NETWORK_HOSTNAME; 19 | 20 | void postDevicePing(); 21 | bool loadConfig(); 22 | void loadKey(const char* keyName, const char* filename, char* data, const uint16_t dataSize, const char* defaultData); 23 | void loadKey(const char* keyName, const char* filename, double *data); 24 | void loadKey(const char* keyName, const char* filename, int32_t *data); 25 | void addKey(const char* key, char* buf, const char *file); 26 | void startWifi(bool loadCfg); 27 | void checkForWifiTimeout(); 28 | 29 | bool wifiTimeout = false; 30 | 31 | //timer that signals the ESP to restart if in broadcast mode for too long 32 | //(generally because it couldnt connect to wifi) 33 | Metro restartTimer = Metro(3 * MINUTE); 34 | 35 | //wifi connect timeout timer (drops into broadcast mode when triggered) 36 | Metro connectTimeout = Metro(20 * SECOND); 37 | 38 | 39 | int progModeCount = 0; 40 | 41 | 42 | netInfo config; 43 | ESPHelper myESP; 44 | 45 | 46 | #ifdef ESP8266 47 | ESP8266WebServer server(80); 48 | #endif 49 | #ifdef ESP32 50 | WebServer server(80); 51 | #endif 52 | 53 | ESPHelperWebConfig configPage(&server, "/config"); 54 | const char* configFileString = "/networkConfig.json"; 55 | 56 | const char* broadcastSSID = NETWORK_HOSTNAME "-Hotspot"; 57 | const char* broadcastPASS = ""; 58 | IPAddress broadcastIP = {192, 168, 1, 1}; 59 | 60 | extern bool justReconnected; 61 | 62 | //ESPHelper 63 | netInfo defaultNet = { .mqttHost = "", //can be blank if not using MQTT 64 | .mqttUser = "", //can be blank 65 | .mqttPass = "", //can be blank 66 | .mqttPort = 1883, //default port for MQTT is 1883 - only change if needed. 67 | .ssid = "", 68 | .pass = ""}; 69 | 70 | 71 | 72 | void postDevicePing(){ 73 | String payload = ""; 74 | payload += String(myESP.getHostname()) + String(','); 75 | payload += String(myESP.getIP()) + String(','); 76 | payload += String(millis() / 1000); 77 | 78 | myESP.publish("/home/deviceStatus", payload.c_str()); 79 | } 80 | 81 | 82 | 83 | //attempt to load a network configuration from the filesystem 84 | bool loadConfig(){ 85 | //check for a good config file and start ESPHelper with the file stored on the ESP 86 | if(ESPHelperFS::begin()){ 87 | 88 | if(ESPHelperFS::validateConfig(configFileString) == GOOD_CONFIG){ 89 | return true; 90 | } 91 | 92 | //if no good config can be loaded (no file/corruption/etc.) then 93 | //attempt to generate a new config and restart the module 94 | else{ 95 | 96 | delay(10); 97 | defaultNet.hostname = HOSTNAME; 98 | ESPHelperFS::createConfig(&defaultNet, configFileString); 99 | ESPHelperFS::end(); 100 | ESP.restart(); 101 | 102 | //note this will probably never end up returning because of the restart call 103 | //but gotta have it here because we always need a path to return 104 | return false; 105 | } 106 | } 107 | 108 | //if the filesystem cannot be started, just fail over to the 109 | //built in network config hardcoded in here 110 | else{ 111 | return false; 112 | } 113 | 114 | return false; 115 | } 116 | void manageESPHelper(int wifiStatus){ 117 | 118 | //if the system has been running for a long time in broadcast mode, restart it 119 | if(wifiStatus == BROADCAST && restartTimer.check()){ 120 | // ESP.restart(); 121 | myESP.disableBroadcast(); 122 | 123 | //after first failure change the restart timer to a small time because 124 | //we probably dont need all that extra time after the first failure 125 | //(ie the first time is possibly because we want to program it but after that 126 | //its probably because of crappy wifi) 127 | 128 | restartTimer.interval(10*SECOND); 129 | restartTimer.reset(); 130 | 131 | connectTimeout.reset(); 132 | myESP.OTA_enable(); 133 | wifiTimeout = false; 134 | justReconnected = true; //reset reconnect val to true for when the ESP does reconnect 135 | Serial.println("Config Mode Timeout. Restarting Normal Station Mode Through ESPHelper"); 136 | return; 137 | } 138 | 139 | //if the unit is broadcasting or connected to wifi then reset the timeout vars 140 | if(wifiStatus == BROADCAST || wifiStatus >= WIFI_ONLY){ 141 | connectTimeout.reset(); 142 | wifiTimeout = false; 143 | } 144 | //otherwise check for a timeout condition and handle setting up broadcast 145 | else if(wifiStatus < WIFI_ONLY){ 146 | checkForWifiTimeout(); 147 | } 148 | 149 | //handle saving a new network config 150 | if(configPage.handle()){ 151 | 152 | myESP.saveConfigFile(configPage.getConfig(), configFileString); 153 | delay(500); 154 | ESP.restart(); 155 | } 156 | } 157 | 158 | //function that checks for no network connection for a period of time 159 | //and starting up AP mode when that time has elapsed 160 | void checkForWifiTimeout(){ 161 | if(connectTimeout.check() && !wifiTimeout){ 162 | 163 | restartTimer.reset(); 164 | wifiTimeout = true; 165 | myESP.broadcastMode(broadcastSSID, broadcastPASS, broadcastIP); 166 | myESP.OTA_setPassword(config.otaPassword); 167 | myESP.OTA_setHostnameWithVersion(config.hostname); 168 | myESP.OTA_enable(); 169 | 170 | Serial.printf("\n\n\ 171 | Could not connect to network.\n\ 172 | Broadcasting our own at %s.\n\ 173 | Connect to network and go to 192.168.1.1/config to setup network settings\n",broadcastSSID); 174 | } 175 | } 176 | 177 | 178 | void startWifi(bool loadCfg){ 179 | static bool cfgLoaded = false; 180 | if(loadCfg){ 181 | cfgLoaded = loadConfig(); 182 | // loadOtherCfg(); 183 | } 184 | 185 | if(cfgLoaded){myESP.begin(configFileString);} 186 | else{myESP.begin(&defaultNet);} 187 | 188 | config = myESP.getNetInfo(); 189 | 190 | //setup other ESPHelper info and enable OTA updates 191 | myESP.setHopping(false); 192 | // myESP.enableHeartbeat(blinkPin); 193 | myESP.OTA_setPassword(config.otaPassword); 194 | myESP.OTA_setHostnameWithVersion(config.hostname); 195 | myESP.OTA_enable(); 196 | 197 | 198 | 199 | delay(10); 200 | //connect to wifi before proceeding. If cannot connect then switch to ap mode and create a network to config from 201 | while(myESP.loop() < WIFI_ONLY){ 202 | checkForWifiTimeout(); 203 | if(wifiTimeout){return;} 204 | delay(10); 205 | } 206 | 207 | 208 | } 209 | 210 | 211 | void loadKey(const char* keyName, const char* filename, char* data, const uint16_t dataSize, const char* defaultData){ 212 | ESPHelperFS::begin(); 213 | String toLoad = ESPHelperFS::loadKey(keyName, filename); 214 | //could not load (0 length) or good load 215 | if(toLoad.length() == 0){ 216 | ESPHelperFS::addKey(keyName, defaultData , filename); 217 | String(defaultData).toCharArray(data, dataSize); 218 | } 219 | else{ 220 | toLoad.toCharArray(data, dataSize); 221 | } 222 | ESPHelperFS::end(); 223 | } 224 | 225 | 226 | void loadKey(const char* keyName, const char* filename, double *data){ 227 | ESPHelperFS::begin(); 228 | String toLoad = ESPHelperFS::loadKey(keyName, filename); 229 | //could not load (0 length) or good load 230 | if(toLoad.length() == 0){ 231 | ESPHelperFS::addKey(keyName, "0.0" , filename); 232 | *data = 0.0; 233 | } 234 | else{*data = toLoad.toFloat();} 235 | ESPHelperFS::end(); 236 | } 237 | 238 | 239 | void loadKey(const char* keyName, const char* filename, int32_t *data){ 240 | ESPHelperFS::begin(); 241 | String toLoad = ESPHelperFS::loadKey(keyName, filename); 242 | //could not load (0 length) or good load 243 | if(toLoad.length() == 0){ 244 | ESPHelperFS::addKey(keyName, "0" , filename); 245 | *data = 0; 246 | } 247 | else{*data = toLoad.toInt();} 248 | ESPHelperFS::end(); 249 | } 250 | 251 | 252 | void addKey(const char* key, char* buf, const char *file){ 253 | ESPHelperFS::begin(); 254 | ESPHelperFS::addKey(key, buf, file); 255 | ESPHelperFS::end(); 256 | } 257 | 258 | 259 | #endif 260 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/pubsubclient/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 | int state = client.state(); 23 | IS_TRUE(state == MQTT_CONNECT_FAILED); 24 | END_IT 25 | } 26 | 27 | int test_connect_fails_on_no_response() { 28 | IT("fails to connect if no response received after 15 seconds"); 29 | ShimClient shimClient; 30 | shimClient.setAllowConnect(true); 31 | PubSubClient client(server, 1883, callback, shimClient); 32 | int rc = client.connect((char*)"client_test1"); 33 | IS_FALSE(rc); 34 | int state = client.state(); 35 | IS_TRUE(state == MQTT_CONNECTION_TIMEOUT); 36 | END_IT 37 | } 38 | 39 | int test_connect_properly_formatted() { 40 | IT("sends a properly formatted connect packet and succeeds"); 41 | ShimClient shimClient; 42 | 43 | shimClient.setAllowConnect(true); 44 | byte expectServer[] = { 172, 16, 0, 2 }; 45 | shimClient.expectConnect(expectServer,1883); 46 | byte connect[] = {0x10,0x18,0x0,0x4,0x4d,0x51,0x54,0x54,0x4,0x2,0x0,0xf,0x0,0xc,0x63,0x6c,0x69,0x65,0x6e,0x74,0x5f,0x74,0x65,0x73,0x74,0x31}; 47 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 48 | 49 | shimClient.expect(connect,26); 50 | shimClient.respond(connack,4); 51 | 52 | PubSubClient client(server, 1883, callback, shimClient); 53 | int state = client.state(); 54 | IS_TRUE(state == MQTT_DISCONNECTED); 55 | 56 | int rc = client.connect((char*)"client_test1"); 57 | IS_TRUE(rc); 58 | IS_FALSE(shimClient.error()); 59 | 60 | state = client.state(); 61 | IS_TRUE(state == MQTT_CONNECTED); 62 | 63 | END_IT 64 | } 65 | 66 | int test_connect_properly_formatted_hostname() { 67 | IT("accepts a hostname"); 68 | ShimClient shimClient; 69 | 70 | shimClient.setAllowConnect(true); 71 | shimClient.expectConnect((char* const)"localhost",1883); 72 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 73 | shimClient.respond(connack,4); 74 | 75 | PubSubClient client((char* const)"localhost", 1883, callback, shimClient); 76 | int rc = client.connect((char*)"client_test1"); 77 | IS_TRUE(rc); 78 | IS_FALSE(shimClient.error()); 79 | 80 | END_IT 81 | } 82 | 83 | 84 | int test_connect_fails_on_bad_rc() { 85 | IT("fails to connect if a bad return code is received"); 86 | ShimClient shimClient; 87 | shimClient.setAllowConnect(true); 88 | byte connack[] = { 0x20, 0x02, 0x00, 0x01 }; 89 | shimClient.respond(connack,4); 90 | 91 | PubSubClient client(server, 1883, callback, shimClient); 92 | int rc = client.connect((char*)"client_test1"); 93 | IS_FALSE(rc); 94 | 95 | int state = client.state(); 96 | IS_TRUE(state == 0x01); 97 | 98 | END_IT 99 | } 100 | 101 | int test_connect_non_clean_session() { 102 | IT("sends a properly formatted non-clean session connect packet and succeeds"); 103 | ShimClient shimClient; 104 | 105 | shimClient.setAllowConnect(true); 106 | byte expectServer[] = { 172, 16, 0, 2 }; 107 | shimClient.expectConnect(expectServer,1883); 108 | byte connect[] = {0x10,0x18,0x0,0x4,0x4d,0x51,0x54,0x54,0x4,0x0,0x0,0xf,0x0,0xc,0x63,0x6c,0x69,0x65,0x6e,0x74,0x5f,0x74,0x65,0x73,0x74,0x31}; 109 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 110 | 111 | shimClient.expect(connect,26); 112 | shimClient.respond(connack,4); 113 | 114 | PubSubClient client(server, 1883, callback, shimClient); 115 | int state = client.state(); 116 | IS_TRUE(state == MQTT_DISCONNECTED); 117 | 118 | int rc = client.connect((char*)"client_test1",0,0,0,0,0,0,0); 119 | IS_TRUE(rc); 120 | IS_FALSE(shimClient.error()); 121 | 122 | state = client.state(); 123 | IS_TRUE(state == MQTT_CONNECTED); 124 | 125 | END_IT 126 | } 127 | 128 | int test_connect_accepts_username_password() { 129 | IT("accepts a username and password"); 130 | ShimClient shimClient; 131 | shimClient.setAllowConnect(true); 132 | 133 | byte connect[] = { 0x10,0x24,0x0,0x4,0x4d,0x51,0x54,0x54,0x4,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}; 134 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 135 | shimClient.expect(connect,0x26); 136 | shimClient.respond(connack,4); 137 | 138 | PubSubClient client(server, 1883, callback, shimClient); 139 | int rc = client.connect((char*)"client_test1",(char*)"user",(char*)"pass"); 140 | IS_TRUE(rc); 141 | IS_FALSE(shimClient.error()); 142 | 143 | END_IT 144 | } 145 | 146 | int test_connect_accepts_username_no_password() { 147 | IT("accepts a username but no password"); 148 | ShimClient shimClient; 149 | shimClient.setAllowConnect(true); 150 | 151 | byte connect[] = { 0x10,0x1e,0x0,0x4,0x4d,0x51,0x54,0x54,0x4,0x82,0x0,0xf,0x0,0xc,0x63,0x6c,0x69,0x65,0x6e,0x74,0x5f,0x74,0x65,0x73,0x74,0x31,0x0,0x4,0x75,0x73,0x65,0x72}; 152 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 153 | shimClient.expect(connect,0x20); 154 | shimClient.respond(connack,4); 155 | 156 | PubSubClient client(server, 1883, callback, shimClient); 157 | int rc = client.connect((char*)"client_test1",(char*)"user",0); 158 | IS_TRUE(rc); 159 | IS_FALSE(shimClient.error()); 160 | 161 | END_IT 162 | } 163 | int test_connect_accepts_username_blank_password() { 164 | IT("accepts a username and blank password"); 165 | ShimClient shimClient; 166 | shimClient.setAllowConnect(true); 167 | 168 | byte connect[] = { 0x10,0x20,0x0,0x4,0x4d,0x51,0x54,0x54,0x4,0xc2,0x0,0xf,0x0,0xc,0x63,0x6c,0x69,0x65,0x6e,0x74,0x5f,0x74,0x65,0x73,0x74,0x31,0x0,0x4,0x75,0x73,0x65,0x72,0x0,0x0}; 169 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 170 | shimClient.expect(connect,0x26); 171 | shimClient.respond(connack,4); 172 | 173 | PubSubClient client(server, 1883, callback, shimClient); 174 | int rc = client.connect((char*)"client_test1",(char*)"user",(char*)"pass"); 175 | IS_TRUE(rc); 176 | IS_FALSE(shimClient.error()); 177 | 178 | END_IT 179 | } 180 | 181 | int test_connect_ignores_password_no_username() { 182 | IT("ignores a password but no username"); 183 | ShimClient shimClient; 184 | shimClient.setAllowConnect(true); 185 | 186 | byte connect[] = {0x10,0x18,0x0,0x4,0x4d,0x51,0x54,0x54,0x4,0x2,0x0,0xf,0x0,0xc,0x63,0x6c,0x69,0x65,0x6e,0x74,0x5f,0x74,0x65,0x73,0x74,0x31}; 187 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 188 | shimClient.expect(connect,26); 189 | shimClient.respond(connack,4); 190 | 191 | PubSubClient client(server, 1883, callback, shimClient); 192 | int rc = client.connect((char*)"client_test1",0,(char*)"pass"); 193 | IS_TRUE(rc); 194 | IS_FALSE(shimClient.error()); 195 | 196 | END_IT 197 | } 198 | 199 | int test_connect_with_will() { 200 | IT("accepts a will"); 201 | ShimClient shimClient; 202 | shimClient.setAllowConnect(true); 203 | 204 | byte connect[] = {0x10,0x30,0x0,0x4,0x4d,0x51,0x54,0x54,0x4,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}; 205 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 206 | shimClient.expect(connect,0x32); 207 | shimClient.respond(connack,4); 208 | 209 | PubSubClient client(server, 1883, callback, shimClient); 210 | int rc = client.connect((char*)"client_test1",(char*)"willTopic",1,0,(char*)"willMessage"); 211 | IS_TRUE(rc); 212 | IS_FALSE(shimClient.error()); 213 | 214 | END_IT 215 | } 216 | 217 | int test_connect_with_will_username_password() { 218 | IT("accepts a will, username and password"); 219 | ShimClient shimClient; 220 | shimClient.setAllowConnect(true); 221 | 222 | byte connect[] = {0x10,0x40,0x0,0x4,0x4d,0x51,0x54,0x54,0x4,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}; 223 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 224 | shimClient.expect(connect,0x42); 225 | shimClient.respond(connack,4); 226 | 227 | PubSubClient client(server, 1883, callback, shimClient); 228 | int rc = client.connect((char*)"client_test1",(char*)"user",(char*)"password",(char*)"willTopic",1,0,(char*)"willMessage"); 229 | IS_TRUE(rc); 230 | IS_FALSE(shimClient.error()); 231 | 232 | END_IT 233 | } 234 | 235 | int test_connect_disconnect_connect() { 236 | IT("connects, disconnects and connects again"); 237 | ShimClient shimClient; 238 | 239 | shimClient.setAllowConnect(true); 240 | byte expectServer[] = { 172, 16, 0, 2 }; 241 | shimClient.expectConnect(expectServer,1883); 242 | byte connect[] = {0x10,0x18,0x0,0x4,0x4d,0x51,0x54,0x54,0x4,0x2,0x0,0xf,0x0,0xc,0x63,0x6c,0x69,0x65,0x6e,0x74,0x5f,0x74,0x65,0x73,0x74,0x31}; 243 | byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; 244 | 245 | shimClient.expect(connect,26); 246 | shimClient.respond(connack,4); 247 | 248 | PubSubClient client(server, 1883, callback, shimClient); 249 | 250 | int state = client.state(); 251 | IS_TRUE(state == MQTT_DISCONNECTED); 252 | 253 | int rc = client.connect((char*)"client_test1"); 254 | IS_TRUE(rc); 255 | IS_FALSE(shimClient.error()); 256 | 257 | state = client.state(); 258 | IS_TRUE(state == MQTT_CONNECTED); 259 | 260 | byte disconnect[] = {0xE0,0x00}; 261 | shimClient.expect(disconnect,2); 262 | 263 | client.disconnect(); 264 | 265 | IS_FALSE(client.connected()); 266 | IS_FALSE(shimClient.connected()); 267 | IS_FALSE(shimClient.error()); 268 | 269 | state = client.state(); 270 | IS_TRUE(state == MQTT_DISCONNECTED); 271 | 272 | shimClient.expect(connect,28); 273 | shimClient.respond(connack,4); 274 | rc = client.connect((char*)"client_test1"); 275 | IS_TRUE(rc); 276 | IS_FALSE(shimClient.error()); 277 | state = client.state(); 278 | IS_TRUE(state == MQTT_CONNECTED); 279 | 280 | END_IT 281 | } 282 | 283 | int main() 284 | { 285 | SUITE("Connect"); 286 | 287 | test_connect_fails_no_network(); 288 | test_connect_fails_on_no_response(); 289 | 290 | test_connect_properly_formatted(); 291 | test_connect_non_clean_session(); 292 | test_connect_accepts_username_password(); 293 | test_connect_fails_on_bad_rc(); 294 | test_connect_properly_formatted_hostname(); 295 | 296 | test_connect_accepts_username_no_password(); 297 | test_connect_ignores_password_no_username(); 298 | test_connect_with_will(); 299 | test_connect_with_will_username_password(); 300 | test_connect_disconnect_connect(); 301 | FINISH 302 | } 303 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /twitterPrinter_pio/lib/QRCode/tests/QrCode.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * QR Code generator library (C++) 3 | * 4 | * Copyright (c) Project Nayuki 5 | * https://www.nayuki.io/page/qr-code-generator-library 6 | * 7 | * (MIT License) 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 9 | * this software and associated documentation files (the "Software"), to deal in 10 | * the Software without restriction, including without limitation the rights to 11 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 12 | * the Software, and to permit persons to whom the Software is furnished to do so, 13 | * subject to the following conditions: 14 | * - The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * - The Software is provided "as is", without warranty of any kind, express or 17 | * implied, including but not limited to the warranties of merchantability, 18 | * fitness for a particular purpose and noninfringement. In no event shall the 19 | * authors or copyright holders be liable for any claim, damages or other 20 | * liability, whether in an action of contract, tort or otherwise, arising from, 21 | * out of or in connection with the Software or the use or other dealings in the 22 | * Software. 23 | */ 24 | 25 | #pragma once 26 | 27 | #include 28 | #include 29 | #include 30 | #include "QrSegment.hpp" 31 | 32 | 33 | namespace qrcodegen { 34 | 35 | /* 36 | * Represents an immutable square grid of black and white cells for a QR Code symbol, and 37 | * provides static functions to create a QR Code from user-supplied textual or binary data. 38 | * This class covers the QR Code model 2 specification, supporting all versions (sizes) 39 | * from 1 to 40, all 4 error correction levels, and only 3 character encoding modes. 40 | */ 41 | class QrCode { 42 | 43 | /*---- Public helper enumeration ----*/ 44 | public: 45 | 46 | /* 47 | * Represents the error correction level used in a QR Code symbol. 48 | */ 49 | class Ecc { 50 | // Constants declared in ascending order of error protection. 51 | public: 52 | const static Ecc LOW, MEDIUM, QUARTILE, HIGH; 53 | 54 | // Fields. 55 | public: 56 | const int ordinal; // (Public) In the range 0 to 3 (unsigned 2-bit integer). 57 | const int formatBits; // (Package-private) In the range 0 to 3 (unsigned 2-bit integer). 58 | 59 | // Constructor. 60 | private: 61 | Ecc(int ord, int fb); 62 | }; 63 | 64 | 65 | 66 | /*---- Public static factory functions ----*/ 67 | public: 68 | 69 | /* 70 | * Returns a QR Code symbol representing the given Unicode text string at the given error correction level. 71 | * As a conservative upper bound, this function is guaranteed to succeed for strings that have 738 or fewer Unicode 72 | * code points (not UTF-16 code units). The smallest possible QR Code version is automatically chosen for the output. 73 | * The ECC level of the result may be higher than the ecl argument if it can be done without increasing the version. 74 | */ 75 | static QrCode encodeText(const char *text, int version, const Ecc &ecl); 76 | 77 | 78 | /* 79 | * Returns a QR Code symbol representing the given binary data string at the given error correction level. 80 | * This function always encodes using the binary segment mode, not any text mode. The maximum number of 81 | * bytes allowed is 2953. The smallest possible QR Code version is automatically chosen for the output. 82 | * The ECC level of the result may be higher than the ecl argument if it can be done without increasing the version. 83 | */ 84 | static QrCode encodeBinary(const std::vector &data, const Ecc &ecl); 85 | 86 | 87 | /* 88 | * Returns a QR Code symbol representing the given data segments with the given encoding parameters. 89 | * The smallest possible QR Code version within the given range is automatically chosen for the output. 90 | * This function allows the user to create a custom sequence of segments that switches 91 | * between modes (such as alphanumeric and binary) to encode text more efficiently. 92 | * This function is considered to be lower level than simply encoding text or binary data. 93 | */ 94 | static QrCode encodeSegments(const std::vector &segs, const Ecc &ecl, 95 | int minVersion=1, int maxVersion=40, int mask=-1, bool boostEcl=true); // All optional parameters 96 | 97 | 98 | 99 | /*---- Instance fields ----*/ 100 | 101 | // Public immutable scalar parameters 102 | public: 103 | 104 | /* This QR Code symbol's version number, which is always between 1 and 40 (inclusive). */ 105 | const int version; 106 | 107 | /* The width and height of this QR Code symbol, measured in modules. 108 | * Always equal to version × 4 + 17, in the range 21 to 177. */ 109 | const int size; 110 | 111 | /* The error correction level used in this QR Code symbol. */ 112 | const Ecc &errorCorrectionLevel; 113 | 114 | /* The mask pattern used in this QR Code symbol, in the range 0 to 7 (i.e. unsigned 3-bit integer). 115 | * Note that even if a constructor was called with automatic masking requested 116 | * (mask = -1), the resulting object will still have a mask value between 0 and 7. */ 117 | private: 118 | int mask; 119 | 120 | // Private grids of modules/pixels (conceptually immutable) 121 | private: 122 | std::vector > modules; // The modules of this QR Code symbol (false = white, true = black) 123 | std::vector > isFunction; // Indicates function modules that are not subjected to masking 124 | 125 | 126 | 127 | /*---- Constructors ----*/ 128 | public: 129 | 130 | /* 131 | * Creates a new QR Code symbol with the given version number, error correction level, binary data array, 132 | * and mask number. This is a cumbersome low-level constructor that should not be invoked directly by the user. 133 | * To go one level up, see the encodeSegments() function. 134 | */ 135 | QrCode(int ver, const Ecc &ecl, const std::vector &dataCodewords, int mask); 136 | 137 | 138 | /* 139 | * Creates a new QR Code symbol based on the given existing object, but with a potentially 140 | * different mask pattern. The version, error correction level, codewords, etc. of the newly 141 | * created object are all identical to the argument object; only the mask may differ. 142 | */ 143 | QrCode(const QrCode &qr, int mask); 144 | 145 | 146 | 147 | /*---- Public instance methods ----*/ 148 | public: 149 | 150 | int getMask() const; 151 | 152 | 153 | /* 154 | * Returns the color of the module (pixel) at the given coordinates, which is either 0 for white or 1 for black. The top 155 | * left corner has the coordinates (x=0, y=0). If the given coordinates are out of bounds, then 0 (white) is returned. 156 | */ 157 | int getModule(int x, int y) const; 158 | 159 | 160 | /* 161 | * Based on the given number of border modules to add as padding, this returns a 162 | * string whose contents represents an SVG XML file that depicts this QR Code symbol. 163 | * Note that Unix newlines (\n) are always used, regardless of the platform. 164 | */ 165 | std::string toSvgString(int border) const; 166 | 167 | 168 | 169 | /*---- Private helper methods for constructor: Drawing function modules ----*/ 170 | private: 171 | 172 | void drawFunctionPatterns(); 173 | 174 | 175 | // Draws two copies of the format bits (with its own error correction code) 176 | // based on the given mask and this object's error correction level field. 177 | void drawFormatBits(int mask); 178 | 179 | 180 | // Draws two copies of the version bits (with its own error correction code), 181 | // based on this object's version field (which only has an effect for 7 <= version <= 40). 182 | void drawVersion(); 183 | 184 | 185 | // Draws a 9*9 finder pattern including the border separator, with the center module at (x, y). 186 | void drawFinderPattern(int x, int y); 187 | 188 | 189 | // Draws a 5*5 alignment pattern, with the center module at (x, y). 190 | void drawAlignmentPattern(int x, int y); 191 | 192 | 193 | // Sets the color of a module and marks it as a function module. 194 | // Only used by the constructor. Coordinates must be in range. 195 | void setFunctionModule(int x, int y, bool isBlack); 196 | 197 | 198 | /*---- Private helper methods for constructor: Codewords and masking ----*/ 199 | private: 200 | 201 | // Returns a new byte string representing the given data with the appropriate error correction 202 | // codewords appended to it, based on this object's version and error correction level. 203 | std::vector appendErrorCorrection(const std::vector &data) const; 204 | 205 | 206 | // Draws the given sequence of 8-bit codewords (data and error correction) onto the entire 207 | // data area of this QR Code symbol. Function modules need to be marked off before this is called. 208 | void drawCodewords(const std::vector &data); 209 | 210 | 211 | // XORs the data modules in this QR Code with the given mask pattern. Due to XOR's mathematical 212 | // properties, calling applyMask(m) twice with the same value is equivalent to no change at all. 213 | // This means it is possible to apply a mask, undo it, and try another mask. Note that a final 214 | // well-formed QR Code symbol needs exactly one mask applied (not zero, not two, etc.). 215 | void applyMask(int mask); 216 | 217 | 218 | // A messy helper function for the constructors. This QR Code must be in an unmasked state when this 219 | // method is called. The given argument is the requested mask, which is -1 for auto or 0 to 7 for fixed. 220 | // This method applies and returns the actual mask chosen, from 0 to 7. 221 | int handleConstructorMasking(int mask); 222 | 223 | 224 | // Calculates and returns the penalty score based on state of this QR Code's current modules. 225 | // This is used by the automatic mask choice algorithm to find the mask pattern that yields the lowest score. 226 | int getPenaltyScore() const; 227 | 228 | 229 | 230 | /*---- Private static helper functions ----*/ 231 | private: 232 | 233 | // Returns a set of positions of the alignment patterns in ascending order. These positions are 234 | // used on both the x and y axes. Each value in the resulting array is in the range [0, 177). 235 | // This stateless pure function could be implemented as table of 40 variable-length lists of unsigned bytes. 236 | static std::vector getAlignmentPatternPositions(int ver); 237 | 238 | 239 | // Returns the number of raw data modules (bits) available at the given version number. 240 | // These data modules are used for both user data codewords and error correction codewords. 241 | // This stateless pure function could be implemented as a 40-entry lookup table. 242 | static int getNumRawDataModules(int ver); 243 | 244 | 245 | // Returns the number of 8-bit data (i.e. not error correction) codewords contained in any 246 | // QR Code of the given version number and error correction level, with remainder bits discarded. 247 | // This stateless pure function could be implemented as a (40*4)-cell lookup table. 248 | static int getNumDataCodewords(int ver, const Ecc &ecl); 249 | 250 | 251 | /*---- Private tables of constants ----*/ 252 | private: 253 | 254 | // For use in getPenaltyScore(), when evaluating which mask is best. 255 | static const int PENALTY_N1; 256 | static const int PENALTY_N2; 257 | static const int PENALTY_N3; 258 | static const int PENALTY_N4; 259 | 260 | static const int16_t NUM_ERROR_CORRECTION_CODEWORDS[4][41]; 261 | static const int8_t NUM_ERROR_CORRECTION_BLOCKS[4][41]; 262 | 263 | 264 | 265 | /*---- Private helper class ----*/ 266 | private: 267 | 268 | /* 269 | * Computes the Reed-Solomon error correction codewords for a sequence of data codewords 270 | * at a given degree. Objects are immutable, and the state only depends on the degree. 271 | * This class exists because the divisor polynomial does not need to be recalculated for every input. 272 | */ 273 | class ReedSolomonGenerator { 274 | 275 | /*-- Immutable field --*/ 276 | private: 277 | 278 | // Coefficients of the divisor polynomial, stored from highest to lowest power, excluding the leading term which 279 | // is always 1. For example the polynomial x^3 + 255x^2 + 8x + 93 is stored as the uint8 array {255, 8, 93}. 280 | std::vector coefficients; 281 | 282 | 283 | /*-- Constructor --*/ 284 | public: 285 | 286 | /* 287 | * Creates a Reed-Solomon ECC generator for the given degree. This could be implemented 288 | * as a lookup table over all possible parameter values, instead of as an algorithm. 289 | */ 290 | ReedSolomonGenerator(int degree); 291 | 292 | 293 | /*-- Method --*/ 294 | public: 295 | 296 | /* 297 | * Computes and returns the Reed-Solomon error correction codewords for the given sequence of data codewords. 298 | * The returned object is always a new byte array. This method does not alter this object's state (because it is immutable). 299 | */ 300 | std::vector getRemainder(const std::vector &data) const; 301 | 302 | 303 | /*-- Static function --*/ 304 | private: 305 | 306 | // Returns the product of the two given field elements modulo GF(2^8/0x11D). The arguments and result 307 | // are unsigned 8-bit integers. This could be implemented as a lookup table of 256*256 entries of uint8. 308 | static uint8_t multiply(uint8_t x, uint8_t y); 309 | 310 | }; 311 | 312 | }; 313 | 314 | } 315 | -------------------------------------------------------------------------------- /twitterPrinter_pio/src/twitterPrinter.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2020 ItKindaWorks All right reserved. 3 | github.com/ItKindaWorks 4 | 5 | This File is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This File 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 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with This File. If not, see . 17 | */ 18 | #include "ESPHelper_base.h" 19 | #include "Adafruit_Thermal.h" 20 | #include "qrcode.h" 21 | #include 22 | #include 23 | 24 | 25 | #define AFFIRM_REQ(SUB_TEXT, SUB_DATA) String("\ 26 |
\ 27 | Updated!\ 28 |
\ 29 | \ 30 |

" SUB_TEXT " " + SUB_DATA + "
\ 31 | \ 32 | \ 33 | ") 34 | 35 | //invalid input http str 36 | const String INVALID_REQUEST_STR = String("\ 37 |

\ 38 | Bad Input\ 39 |
\ 40 | \ 41 |

400: Invalid Request
\ 42 | \ 43 | \ 44 | "); 45 | 46 | ///////////////////////// Pin Definitions ///////////////////////// 47 | 48 | const int buttonPin = D2; 49 | Bounce pushbutton = Bounce(buttonPin, 10); // 10 ms debounce 50 | 51 | 52 | ///////////////////////// Networking ///////////////////////// 53 | 54 | //bool set to true when the system has just connected or reconnected. Allows us to ping the IP 55 | //or do whatever else is necessary when we connect to wifi 56 | bool justReconnected = true; 57 | 58 | 59 | 60 | ///////////////////////// Timers ///////////////////////// 61 | 62 | 63 | ///////////////////////// Sensors ///////////////////////// 64 | 65 | 66 | 67 | ///////////////////////// Config Keys ///////////////////////// 68 | 69 | char topic[64]; 70 | char statusTopic[64]; 71 | 72 | 73 | ///////////////////////// Other ///////////////////////// 74 | 75 | bool flippedPrinting = true; 76 | bool printQRLinks = true; 77 | 78 | SoftwareSerial mySerial; 79 | const int PRINTER_RX = D5; 80 | const int PRINTER_TX = D6; 81 | Adafruit_Thermal printer(&mySerial); // Pass addr to printer constructor 82 | 83 | const char upsideOn[] = { 27, 123, 1, 0}; 84 | const char upsideOff[] = { 27, 123, 0, 0}; 85 | 86 | 87 | void setup() { 88 | Serial.begin(115200); 89 | delay(500); 90 | 91 | 92 | ///////////////////////// IO init ///////////////////////// 93 | 94 | mySerial.begin(19200, SWSERIAL_8N1, PRINTER_RX, PRINTER_TX, false, 95, 11); 95 | delay(500); 96 | printer.begin(); // Init printer (same regardless of serial type) 97 | 98 | printer.wake(); 99 | printer.feed(2); 100 | basicPrint("Starting Up Please Wait...", 2, true); 101 | 102 | pinMode(buttonPin, INPUT_PULLUP); 103 | 104 | ///////////////////////// Network Init ///////////////////////// 105 | 106 | //startup the wifi and web server 107 | startWifi(true); 108 | loadOtherCfg(); 109 | configPage.fillConfig(&config); 110 | configPage.begin(config.hostname); 111 | server.on("/", HTTP_GET, handleStatus); 112 | server.on("/topicUpdate", HTTP_POST, handleTopicUpdate); 113 | server.on("/flippedPrinting", HTTP_POST, handleToggleFlipPrint); 114 | server.on("/printQRLinks", HTTP_POST, handleToggleQRLink); 115 | 116 | //UNCOMMENT THIS LINE TO ENABLE MQTT CALLBACK 117 | myESP.setCallback(callback); 118 | myESP.addSubscription(topic); 119 | myESP.addSubscription("/home/devicePing"); 120 | 121 | server.begin(); // Actually start the server 122 | 123 | //print a little signature ;) 124 | printer.wake(); 125 | if(flippedPrinting){mySerial.write(upsideOff, 4);} 126 | printQR("https://youtube.com/itkindaworks"); 127 | defaultPrintSettings(); 128 | printer.sleep(); 129 | 130 | 131 | basicPrint("Booting Finished", 2, true); 132 | 133 | } 134 | 135 | void loop(){ 136 | while(1){ 137 | ///////////////////////// Background Routines ///////////////////////// 138 | 139 | 140 | ///////////////////////// Network Handling ///////////////////////// 141 | 142 | //get the current status of ESPHelper 143 | int espHelperStatus = myESP.loop(); 144 | manageESPHelper(espHelperStatus); 145 | 146 | if(espHelperStatus >= WIFI_ONLY){ 147 | 148 | if(espHelperStatus == FULL_CONNECTION){ 149 | //full connection loop code here 150 | if(pushbutton.update()){ 151 | if (pushbutton.risingEdge()) { 152 | String outTopic = String(topic); 153 | outTopic += "/signal"; 154 | myESP.publish(outTopic.c_str(), "1"); 155 | } 156 | } 157 | } 158 | 159 | if(justReconnected){ 160 | //post to mqtt if connected 161 | if(espHelperStatus == FULL_CONNECTION){ 162 | myESP.publish("/home/IP", String(String(myESP.getHostname()) + " -- " + String(myESP.getIP()) ).c_str() ); 163 | } 164 | Serial.print("Connected to network with IP: "); 165 | Serial.println(myESP.getIP()); 166 | 167 | if(flippedPrinting == true){ 168 | basicPrint(myESP.getIP().c_str(), 0, true); 169 | basicPrint("Connected to network with IP: ", 2, true); 170 | } 171 | else{ 172 | basicPrint("Connected to network with IP: ", 0, true); 173 | basicPrint(myESP.getIP().c_str(), 2, true); 174 | } 175 | 176 | justReconnected = false; 177 | } 178 | 179 | } 180 | 181 | //loop delay can be down to 1ms if needed. Shouldn't go below that though 182 | //(ie dont use 'yield' if it can be avoided) 183 | delay(5); 184 | } 185 | 186 | } 187 | 188 | /** 189 | * @brief mqtt callback function 190 | * 191 | * @param topic topic string 192 | * @param payload payload string (NOT NULL TERMINATED) 193 | * @param length length of the payload 194 | */ 195 | void callback(char* topic, uint8_t* payload, unsigned int length) { 196 | //convert topic to string to make it easier to work with if complex 197 | //comparisons are needed. 198 | String topicStr = topic; 199 | 200 | //fix error in mqtt not including a null terminator and 201 | //create a string to make the payload easier to work with if complex 202 | //comparisons are needed. 203 | char newPayload[500]; 204 | memcpy(newPayload, payload, length); 205 | newPayload[length] = '\0'; 206 | String payloadStr = newPayload; 207 | 208 | if(topicStr.equals("/home/devicePing")){ 209 | postDevicePing(); 210 | return; 211 | } 212 | 213 | //make sure the printer is defaulted 214 | defaultPrintSettings(); 215 | 216 | //header and footer strings 217 | char* header = "\ 218 | -----------------------\n\ 219 | ------ New Tweet ------\n\ 220 | -----------------------"; 221 | char* footer = "-----------------------"; 222 | 223 | //invert the order things are printed in if the 224 | //text is to be printed in reverse order 225 | if(flippedPrinting == true){ 226 | thermalPrint(footer, strlen(footer), 2); 227 | if(printQRLinks){printBarcodeLink(payloadStr);} 228 | thermalPrint(newPayload, length, 2); 229 | thermalPrint(header, strlen(header), 3); 230 | } 231 | else{ 232 | thermalPrint(header, strlen(header), 2); 233 | thermalPrint(newPayload, length, 2); 234 | if(printQRLinks){printBarcodeLink(payloadStr);} 235 | thermalPrint(footer, strlen(footer), 3); 236 | } 237 | } 238 | 239 | /** 240 | * @brief basic thermal print function 241 | * 242 | * @param inStr string to be printed 243 | * @param feedCount number of line feeds after printed text 244 | * @param defaultFmt should we use the default formatting options 245 | */ 246 | void basicPrint(const char* inStr, int feedCount, bool defaultFmt){ 247 | printer.wake(); 248 | if(defaultFmt){defaultPrintSettings();} 249 | printer.println(inStr); 250 | printer.feed(feedCount); 251 | printer.sleep(); // Tell printer to sleep 252 | } 253 | 254 | /** 255 | * @brief search for and print a qr code to the last twitter t.co/... link in a tweet (usually a subtweet, picture, or link to article) 256 | * 257 | * @param inStr tweet string to search for a link to convert to a qr code 258 | */ 259 | void printBarcodeLink(String inStr){ 260 | 261 | //find the index of the last link 262 | int index = -1; 263 | if(flippedPrinting == false){index =inStr.lastIndexOf("https://t.co/");} 264 | else{index =inStr.indexOf("https://t.co/");} //flipped printing requires searching from the "start" of the string (the end of the tweet) 265 | 266 | //if nothing was found, end 267 | if(index == -1){return;} 268 | 269 | //generate a link only string 270 | String link = inStr.substring(index, index+23); 271 | 272 | //wake the printer and prep for printing 273 | printer.wake(); 274 | if(flippedPrinting){mySerial.write(upsideOff, 4);} 275 | 276 | //print out the qr code 277 | printQR(link); 278 | 279 | //reset the printer back to default settings and sleep 280 | defaultPrintSettings(); 281 | printer.sleep(); 282 | 283 | } 284 | 285 | /** 286 | * @brief print a qr code based on a string 287 | * 288 | * @param text piece of text to be converted into a qr code 289 | */ 290 | void printQR(String text){ 291 | 292 | //wake the printer and setup formatting 293 | printer.wake(); 294 | printer.justify('C'); 295 | printer.setCharSpacing(0); 296 | 297 | //set zero line spacing 298 | mySerial.write(27); 299 | mySerial.write(51); 300 | mySerial.write((byte)0); 301 | 302 | //print an extra line feed for spacing 303 | printer.feed(1); 304 | 305 | // Create the QR code 306 | Serial.println("Generating QR Code"); 307 | QRCode qrcode; 308 | uint8_t qrcodeData[qrcode_getBufferSize(3)]; 309 | qrcode_initText(&qrcode, qrcodeData, 3, 0, text.c_str()); 310 | 311 | 312 | //print the code 313 | Serial.println("printing QR Code\n\n"); 314 | 315 | if(flippedPrinting == false){ //handle regular (right side up) printing of the code 316 | 317 | for (int x = 0; x < qrcode.size; x+=2) { //x+=2 because each printed character represents 2 lines of the qr code 318 | for (int y = 0; y < qrcode.size; y++) { 319 | 320 | //since each printed char represents 2 lines of the qr code, we have to make sure to print the right character 321 | //so each of these if statements looks at the qr 'bit' on the current line and the next line of the qr code 322 | //and figures out which char needs to be printed. 323 | if (qrcode_getModule(&qrcode, x, y) && qrcode_getModule(&qrcode, x+1, y)) {mySerial.write(219);} 324 | else if (!qrcode_getModule(&qrcode, x, y) && qrcode_getModule(&qrcode, x+1, y)) {mySerial.write(220);} 325 | else if (qrcode_getModule(&qrcode, x, y) && !qrcode_getModule(&qrcode, x+1, y)) {mySerial.write(223);} 326 | else if (!qrcode_getModule(&qrcode, x, y) && !qrcode_getModule(&qrcode, x+1, y)) {mySerial.print(" ");} 327 | } 328 | printer.feed(1); 329 | } 330 | } 331 | else{ 332 | //when printing upside down we have to start from the bottom of the code and work upwards which is why x starts at qrcode.size 333 | for (int x = qrcode.size; x >0; x-=2) { //x-=2 because each printed character represents 2 lines of the qr code 334 | for (int y = 0; y < qrcode.size; y++) { 335 | //see note above - this is the same but opposite 336 | if (qrcode_getModule(&qrcode, x, y) && qrcode_getModule(&qrcode, x-1, y)) {mySerial.write(219);} 337 | else if (!qrcode_getModule(&qrcode, x, y) && qrcode_getModule(&qrcode, x-1, y)) {mySerial.write(220);} 338 | else if (qrcode_getModule(&qrcode, x, y) && !qrcode_getModule(&qrcode, x-1, y)) {mySerial.write(223);} 339 | else if (!qrcode_getModule(&qrcode, x, y) && !qrcode_getModule(&qrcode, x-1, y)) {mySerial.print(" ");} 340 | } 341 | printer.feed(1); 342 | } 343 | } 344 | 345 | //turn the printer off when done 346 | printer.sleep(); 347 | } 348 | 349 | /** 350 | * @brief sets the printer back to the expected default formatting 351 | * 352 | */ 353 | void defaultPrintSettings(){ 354 | printer.wake(); 355 | printer.setDefault(); 356 | if(flippedPrinting){mySerial.write(upsideOn, 4);} 357 | printer.justify('C'); 358 | printer.feed(1); 359 | printer.sleep(); 360 | } 361 | 362 | /** 363 | * @brief print text using word wrapping 364 | * 365 | * @param text ptr to string to be printed 366 | * @param len size of the string 367 | * @param linebreaksCount number of breaks to insert after the printed text 368 | */ 369 | void thermalPrint(char* text, int len, int linebreakCount){ 370 | printer.wake(); 371 | 372 | 373 | const int LINE_LEN = 32; 374 | // const int LINE_LEN = 10; 375 | int lineCurChar = 0; 376 | 377 | for(int i = 0; i < len; i++){ 378 | if(text[i] != '\n'){ 379 | int charsLeft = LINE_LEN - lineCurChar; 380 | 381 | if(shouldNewline(&text[i], len-i, charsLeft, LINE_LEN)){ 382 | printer.feed(1); 383 | lineCurChar = 0; 384 | } 385 | 386 | printer.print(text[i]); 387 | lineCurChar++; 388 | } 389 | else{ 390 | printer.feed(1); 391 | lineCurChar = 0; 392 | } 393 | } 394 | 395 | printer.feed(linebreakCount); 396 | printer.sleep(); 397 | } 398 | 399 | /** 400 | * @brief figures out whether a string needs to wrap to the next line to keep from breaking up words 401 | * 402 | * @param text string to check (should generally be used with a given str index, ie &text[i] ) 403 | * @param len total length of the string 404 | * @param charsLeft characters left in the line 405 | * @param lineLen total line length 406 | * @return true if we need to insert a newline now 407 | * @return false if no newline is needed at the moment 408 | */ 409 | bool shouldNewline(char* text, int len, int charsLeft, int lineLen){ 410 | if (len < charsLeft){return false;} 411 | 412 | //search for newline or space 413 | for(int i = 0; i < charsLeft; i++){ 414 | if(text[i] == '\n' || text[i] == ' '){ 415 | //if we find a newline/space before the end of the line, then we dont need a newline 416 | //manually inserted now 417 | return false; 418 | } 419 | } 420 | 421 | //find length of word 422 | int wordSize = 0; 423 | for(int i = 0; i < len; i++){ 424 | if(text[i] == '\n' || text[i] == ' '){break;} 425 | wordSize++; 426 | } 427 | 428 | //if the word is longer than a line, ignore the newline and just let the printer wrap it 429 | if(wordSize > lineLen){return false;} 430 | 431 | //otherwise, if we have gotten here then yes we do need to insert a newline now 432 | else{return true;} 433 | } 434 | 435 | 436 | 437 | void loadOtherCfg(){ 438 | ESPHelperFS::begin(); 439 | 440 | //Remember to change this to whatever file you want to store/read your custom config from 441 | const char* file = "/config.json"; 442 | 443 | //read the topic from memory (or use a default topic if there is an error) 444 | loadKey("topic", file, topic, sizeof(topic), "/home/test"); 445 | //create a temporary string to do some concating to eventually assign to the status topic 446 | String tempTopic = topic; 447 | tempTopic += "/status"; 448 | tempTopic.toCharArray(statusTopic, sizeof(statusTopic)); 449 | 450 | 451 | int inverted = 0; 452 | int qrCode = 0; 453 | 454 | loadKey("flippedPrinting", file, &inverted); 455 | loadKey("printQRLinks", file, &qrCode); 456 | 457 | if(inverted){flippedPrinting = true;} 458 | else{flippedPrinting = false;} 459 | 460 | if(qrCode){printQRLinks = true;} 461 | else{printQRLinks = false;} 462 | 463 | ESPHelperFS::end(); 464 | } 465 | 466 | 467 | 468 | 469 | //main config page that allows user to enter in configuration info 470 | void handleStatus() { 471 | server.send(200, "text/html", \ 472 | String("\ 473 |

\ 474 | Device Info\ 475 |
\ 476 | \ 477 |

System Status
\ 478 | Device Name: " + String(config.hostname) + "
\ 479 | Connected SSID: " + String(myESP.getSSID()) + "
\ 480 | Device IP: " + String(myESP.getIP()) + "
\ 481 | Uptime (ms): " + String(millis()) + "

\ 482 |

\ 483 | \ 484 | \ 485 | \ 489 | \ 490 | \ 491 | \ 492 | \ 493 | \ 494 |
\ 495 | Update Topic:
\ 496 |
\ 497 | \ 498 | \ 499 |
\ 500 |
\ 501 | \ 502 | \ 503 |
\ 504 | Print QR Code: " + String(printQRLinks ? "Enabled" : "Disabled") + "
\ 505 | \ 506 | \ 507 |
\ 508 |
\ 509 | \ 510 | \ 511 |
\ 512 | Flipped text printing: " + String(flippedPrinting ? "Enabled" : "Disabled") + "
\ 513 | \ 514 | \ 515 | ")); 516 | } 517 | 518 | 519 | //handler function for updating the relay timer 520 | void handleTopicUpdate() { 521 | 522 | const char* keyName = "topic"; 523 | 524 | //Remember to change this to whatever file you want to store/read your custom config from 525 | const char* file = "/config.json"; 526 | 527 | //make sure that all the arguments exist and that at least an SSID and hostname have been entered 528 | if(!server.hasArg(keyName)){ 529 | server.send(400, "text/plain", INVALID_REQUEST_STR); 530 | return; 531 | } 532 | 533 | //handle int/float 534 | // int data = server.arg(keyName).toInt(); 535 | // char buf[20]; 536 | // String tmp = String(data); 537 | // tmp.toCharArray(buf, sizeof(buf)); 538 | 539 | //handle string 540 | char buf[64]; 541 | server.arg(keyName).toCharArray(buf, sizeof(buf)); 542 | 543 | myESP.removeSubscription(topic); 544 | 545 | //save the key to flash and refresh data var with data from flash 546 | addKey(keyName, buf , file); 547 | loadKey(keyName, file, topic, sizeof(topic), "/home/test"); 548 | 549 | myESP.addSubscription(topic); 550 | 551 | //tell the user that the config is loaded in and the module is restarting 552 | server.send(200, "text/html",AFFIRM_REQ("Updated Topic To: " , String(topic))); 553 | 554 | } 555 | 556 | void handleToggleFlipPrint(){ 557 | const char* keyName = "flippedPrinting"; 558 | 559 | //Remember to change this to whatever file you want to store/read your custom config from 560 | const char* file = "/config.json"; 561 | 562 | flippedPrinting = !flippedPrinting; 563 | 564 | //save the key to flash and refresh data var with data from flash 565 | addKey(keyName, flippedPrinting ? (char*)"1" : (char*)"0" , file); 566 | 567 | //tell the user that the config is loaded in and the module is restarting 568 | server.send(200, "text/html",AFFIRM_REQ("Flipped printing has been ", String(flippedPrinting ? "Enabled" : "Disabled"))); 569 | } 570 | 571 | void handleToggleQRLink(){ 572 | const char* keyName = "printQRLinks"; 573 | 574 | //Remember to change this to whatever file you want to store/read your custom config from 575 | const char* file = "/config.json"; 576 | 577 | printQRLinks = !printQRLinks; 578 | 579 | //save the key to flash and refresh data var with data from flash 580 | addKey(keyName, printQRLinks ? (char*)"1" : (char*)"0" , file); 581 | 582 | //tell the user that the config is loaded in and the module is restarting 583 | server.send(200, "text/html",AFFIRM_REQ("QR Code printing has been ", String(printQRLinks ? "Enabled" : "Disabled"))); 584 | } 585 | --------------------------------------------------------------------------------