├── .gitignore ├── library.properties ├── keywords.txt ├── license.txt ├── README.md ├── src ├── esp8266Twitter.h └── esp8266Twitter.cpp └── examples └── simpletweet └── simpletweet.ino /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=esp8266twitter 2 | version=0.1 3 | author=chaeplin 4 | maintainer=chaeplin 5 | sentence=direct text post using esp8266/Arduino without 3rd party api 6 | paragraph=direct text post using esp8266/Arduino without 3rd party api 7 | category=Communication 8 | url=https://github.com/chaeplin/esp8266twitter 9 | architectures=esp8266 10 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ########################################### 2 | # Syntax Coloring Map For esp8266twitter 3 | ########################################### 4 | 5 | ########################################### 6 | # Datatypes (KEYWORD1) 7 | ########################################### 8 | 9 | esp8266twitter KEYWORD1 10 | 11 | ########################################### 12 | # Methods and Functions (KEYWORD2) 13 | ########################################### 14 | 15 | esp8266Twitter KEYWORD2 16 | tweet KEYWORD2 17 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 chaeplin at gmail.com 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | esp8266twitter 2 | =============== 3 | 4 | direct text post using esp8266/Arduino without 3rd party api. 5 | 6 | 7 | https://dev.twitter.com/rest/reference/post/statuses/update 8 | 9 | ##### Based on 10 | 11 | - tweeting_silicon : http://harizanov.com/2015/06/tweeting-silicon/ 12 | - https://github.com/igrr/axtls-8266/blob/master/crypto/hmac.c 13 | - http://hardwarefun.com/tutorials/url-encoding-in-arduino 14 | 15 | 16 | ##### 17 | 18 | - Use ntp or rtc to sync time 19 | - constructors : esp8266Twitter esp8266Twitter(consumer_key, consumer_secret, access_token, access_secret); 20 | - to tweet : esp8266Twitter.tweet(message, value_timestamp, value_nonce) 21 | 22 | 23 | ##### Limitations 24 | 25 | - no rate limit checking 26 | - no 140 limit checking 27 | 28 | ##### To use oauth : 29 | 30 | - make an app at https://apps.twitter.com 31 | - generate Access Token / Secret. 32 | - Use 4 keys to sketch 33 | 34 | 35 | ##### for image on spiffs 36 | - post with media upload (if image is big, timout will occur) : https://github.com/chaeplin/esp8266_and_arduino/blob/master/_56-gopro-control/a-09-twitter-image-post/a-09-twitter-image-post.ino 37 | - post with APPEND(chunked) : https://github.com/chaeplin/esp8266_and_arduino/blob/master/_56-gopro-control/a-09-twitter-image-post/a-09-twitter-image-post.ino 38 | - upload image to twitter is slow(3 ~ 4KB/s) 39 | 40 | Enjoy. 41 | 42 | // chaeplin -------------------------------------------------------------------------------- /src/esp8266Twitter.h: -------------------------------------------------------------------------------- 1 | /* 2 | esp8266twitter.h - direct text posting to twitter 3 | chaeplin at gmail.com 4 | */ 5 | 6 | #ifndef esp8266Twitter_h 7 | #define esp8266Twitter_h 8 | 9 | #include "Arduino.h" 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #define SHA1_SIZE 20 16 | 17 | #define BASE_HOST "api.twitter.com" 18 | #define BASE_URL "https://api.twitter.com/1.1/statuses/update.json" 19 | #define BASE_URI "/1.1/statuses/update.json" 20 | #define HTTPSPORT 443 21 | 22 | #define KEY_HTTP_METHOD "POST" 23 | #define KEY_CONSUMER_KEY "oauth_consumer_key" 24 | #define KEY_NONCE "oauth_nonce" 25 | #define KEY_SIGNATURE_METHOD "oauth_signature_method" 26 | #define KEY_TIMESTAMP "oauth_timestamp" 27 | #define KEY_TOKEN "oauth_token" 28 | #define KEY_VERSION "oauth_version" 29 | #define KEY_SIGNATURE "oauth_signature" 30 | #define KEY_MEDIA_ID "media_id" 31 | #define KEY_MEDIA_TYPE "media_type" 32 | #define KEY_MEDIA_IDS "media_ids" 33 | 34 | #define VALUE_SIGNATURE_METHOD "HMAC-SHA1" 35 | #define VALUE_VERSION "1.0" 36 | 37 | #define KEY_STATUS "status" 38 | #define UPLOAD_COMMAND "command" 39 | 40 | #define UPLOAD_BASE_HOST "upload.twitter.com" 41 | #define UPLOAD_BASE_URL "https://upload.twitter.com/1.1/media/upload.json" 42 | #define UPLOAD_BASE_URI "/1.1/media/upload.json" 43 | #define UPLOAD_OAUTH_KEY "oauth_body_hash" 44 | 45 | #define UPLOAD_CMD_INIT "INIT" 46 | #define UPLOAD_CMD_APPEND "APPEND" 47 | #define UPLOAD_CMD_FINALIZE "FINALIZE" 48 | 49 | #define UPLOAD_MEDIA_TYPE "image/jpeg" 50 | #define UPLOAD_MEDIA_SIZE "total_bytes" 51 | #define UPLOAD_MEDIA_SEG_INDX "segment_index" 52 | 53 | class esp8266Twitter 54 | { 55 | 56 | private: 57 | uint32_t value_timestamp; 58 | uint32_t value_nonce; 59 | const char* value_status; 60 | void ssl_hmac_sha1(const uint8_t *msg, int length, const uint8_t *key, int key_len, uint8_t *digest); 61 | String URLEncode(const char* msg); 62 | String make_signature(const char* secret_one, const char* secret_two, String base_string); 63 | bool do_http_text_post(String OAuth_header); 64 | String make_OAuth_header(String oauth_signature); 65 | String make_signature(String base_string); 66 | String make_base_string(String para_string); 67 | String make_para_string(); 68 | esp8266Twitter& setKeys(const char * CONSUMER_KEY, const char * CONSUMER_SECRET, const char * ACCESS_TOKEN, const char * ACCESS_SECRET); 69 | const char* consumerkey; 70 | const char* consumersecret; 71 | const char* accesstoken; 72 | const char* accessscecret; 73 | const char* api_fingerprint = "AB 60 BB B5 F1 B9 A7 7E BE 68 1B BF 35 3F B3 C2 F9 B4 D2 44"; 74 | const char* upload_fingerprint = "48 CD EF 6B F7 F0 D3 8A 3C BD D2 FA E4 0A 29 15 EF 7D 72 1C"; 75 | 76 | 77 | public: 78 | esp8266Twitter(const char *, const char *, const char *, const char *); 79 | boolean tweet(const char* message, uint32_t timestamp, uint32_t nonce); 80 | }; 81 | 82 | #endif -------------------------------------------------------------------------------- /examples/simpletweet/simpletweet.ino: -------------------------------------------------------------------------------- 1 | // https://github.com/PaulStoffregen/Time 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | extern "C" 8 | { 9 | #include "user_interface.h" 10 | } 11 | 12 | #define WIFI_SSID "..." 13 | #define WIFI_PASSWORD "...." 14 | #define TIME_SERVER { xxx, xxx, xxx, xxx } 15 | 16 | #define ConsumerKey "...." 17 | #define ConsumerSecret "...." 18 | #define AccessToken "...." 19 | #define AccessSecret "...." 20 | 21 | const char* ssid = WIFI_SSID; 22 | const char* password = WIFI_PASSWORD; 23 | IPAddress time_server = TIME_SERVER; 24 | // twitter 25 | const char* consumer_key = ConsumerKey; 26 | const char* consumer_secret = ConsumerSecret; 27 | const char* access_token = AccessToken; 28 | const char* access_secret = AccessSecret; 29 | 30 | WiFiClientSecure client; 31 | WiFiUDP udp; 32 | 33 | unsigned int localPort = 12390; 34 | const int timeZone = 9; 35 | 36 | bool x; 37 | int y; 38 | 39 | // 40 | esp8266Twitter esp8266Twitter(consumer_key, consumer_secret, access_token, access_secret); 41 | 42 | void wifi_connect() 43 | { 44 | Serial.print("[WIFI] start millis : "); 45 | Serial.println(millis()); 46 | WiFi.mode(WIFI_STA); 47 | WiFi.begin(ssid, password); 48 | 49 | int Attempt = 0; 50 | while (WiFi.status() != WL_CONNECTED) 51 | { 52 | delay(100); 53 | Attempt++; 54 | if (Attempt == 300) 55 | { 56 | ESP.restart(); 57 | } 58 | } 59 | Serial.print("[WIFI] connected millis : "); 60 | Serial.print(millis()); 61 | Serial.print(" - "); 62 | Serial.println(WiFi.localIP()); 63 | } 64 | 65 | void setup() 66 | { 67 | Serial.begin(115200); 68 | while (!Serial) 69 | { 70 | ; // wait for serial port to connect. 71 | } 72 | Serial.println(); 73 | 74 | wifi_connect(); 75 | 76 | udp.begin(localPort); 77 | setSyncProvider(getNtpTime); 78 | 79 | if (timeStatus() == timeNotSet) 80 | { 81 | setSyncProvider(getNtpTime); 82 | } 83 | 84 | x = true; 85 | y = 0; 86 | } 87 | 88 | time_t prevDisplay = 0; 89 | 90 | void loop() { 91 | if (WiFi.status() == WL_CONNECTED) 92 | { 93 | if (now() != prevDisplay) 94 | { 95 | prevDisplay = now(); 96 | if (timeStatus() == timeSet) 97 | { 98 | digitalClockDisplay(); 99 | 100 | if (x && y == 10) 101 | { 102 | Serial.print("[TWEET] tweet : "); 103 | tweeting(); 104 | x = false; 105 | } 106 | } 107 | y++; 108 | } 109 | } 110 | else 111 | { 112 | wifi_connect(); 113 | setSyncProvider(getNtpTime); 114 | } 115 | } 116 | 117 | void tweeting() 118 | { 119 | const char* value_status = "esp-01 + direct tweet / test 04"; 120 | uint32_t value_timestamp = now(); 121 | uint32_t value_nonce = *(volatile uint32_t *)0x3FF20E44; 122 | 123 | Serial.println(value_status); 124 | if (esp8266Twitter.tweet(value_status, value_timestamp, value_nonce)) 125 | { 126 | Serial.println("[TWEET] result : ok"); 127 | } 128 | else 129 | { 130 | Serial.println("[TWEET] tweet : failed"); 131 | } 132 | } 133 | 134 | /*-------- NTP code ----------*/ 135 | const int NTP_PACKET_SIZE = 48; 136 | byte packetBuffer[NTP_PACKET_SIZE]; 137 | 138 | time_t getNtpTime() 139 | { 140 | while (udp.parsePacket() > 0) ; 141 | sendNTPpacket(time_server); 142 | uint32_t beginWait = millis(); 143 | while (millis() - beginWait < 2500) 144 | { 145 | int size = udp.parsePacket(); 146 | if (size >= NTP_PACKET_SIZE) 147 | { 148 | udp.read(packetBuffer, NTP_PACKET_SIZE); 149 | unsigned long secsSince1900; 150 | secsSince1900 = (unsigned long)packetBuffer[40] << 24; 151 | secsSince1900 |= (unsigned long)packetBuffer[41] << 16; 152 | secsSince1900 |= (unsigned long)packetBuffer[42] << 8; 153 | secsSince1900 |= (unsigned long)packetBuffer[43]; 154 | return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR; 155 | } 156 | } 157 | return 0; 158 | } 159 | 160 | void sendNTPpacket(IPAddress & address) 161 | { 162 | memset(packetBuffer, 0, NTP_PACKET_SIZE); 163 | packetBuffer[0] = 0b11100011; 164 | packetBuffer[1] = 0; 165 | packetBuffer[2] = 6; 166 | packetBuffer[3] = 0xEC; 167 | packetBuffer[12] = 49; 168 | packetBuffer[13] = 0x4E; 169 | packetBuffer[14] = 49; 170 | packetBuffer[15] = 52; 171 | udp.beginPacket(address, 123); 172 | udp.write(packetBuffer, NTP_PACKET_SIZE); 173 | udp.endPacket(); 174 | } 175 | 176 | 177 | void digitalClockDisplay() 178 | { 179 | Serial.print("[TIME] "); 180 | Serial.print(hour()); 181 | printDigits(minute()); 182 | printDigits(second()); 183 | Serial.print(" "); 184 | Serial.print(day()); 185 | Serial.print(" "); 186 | Serial.print(month()); 187 | Serial.print(" "); 188 | Serial.println(year()); 189 | } 190 | 191 | void printDigits(int digits) 192 | { 193 | Serial.print(":"); 194 | if (digits < 10) 195 | Serial.print('0'); 196 | Serial.print(digits); 197 | } 198 | 199 | // end 200 | -------------------------------------------------------------------------------- /src/esp8266Twitter.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | esp8266twitter.cpp - direct text posting to twitter 3 | chaeplin at gmail.com 4 | */ 5 | 6 | #include "esp8266twitter.h" 7 | #include "Arduino.h" 8 | 9 | extern "C" 10 | { 11 | typedef struct 12 | { 13 | uint32_t Intermediate_Hash[SHA1_SIZE / 4]; /* Message Digest */ 14 | uint32_t Length_Low; /* Message length in bits */ 15 | uint32_t Length_High; /* Message length in bits */ 16 | uint16_t Message_Block_Index; /* Index into message block array */ 17 | uint8_t Message_Block[64]; /* 512-bit message blocks */ 18 | } SHA1_CTX; 19 | 20 | void SHA1_Init(SHA1_CTX *); 21 | void SHA1_Update(SHA1_CTX *, const uint8_t * msg, int len); 22 | void SHA1_Final(uint8_t *digest, SHA1_CTX *); 23 | } 24 | 25 | esp8266Twitter::esp8266Twitter(const char * CONSUMER_KEY, const char * CONSUMER_SECRET, const char * ACCESS_TOKEN, const char * ACCESS_SECRET) 26 | { 27 | setKeys(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_SECRET); 28 | } 29 | 30 | boolean esp8266Twitter::tweet(const char* message, uint32_t timestamp, uint32_t nonce) 31 | { 32 | bool rtn = false; 33 | 34 | this->value_timestamp = timestamp; 35 | this->value_nonce = nonce; 36 | this->value_status = message; 37 | 38 | String para_string = make_para_string(); 39 | String base_string = make_base_string(para_string); 40 | String oauth_signature = make_signature(base_string); 41 | String OAuth_header = make_OAuth_header(oauth_signature); 42 | rtn = do_http_text_post(OAuth_header); 43 | 44 | return rtn; 45 | } 46 | 47 | // https://github.com/igrr/axtls-8266/blob/master/crypto/hmac.c 48 | void esp8266Twitter::ssl_hmac_sha1(const uint8_t *msg, int length, const uint8_t *key, int key_len, uint8_t *digest) 49 | { 50 | SHA1_CTX context; 51 | uint8_t k_ipad[64]; 52 | uint8_t k_opad[64]; 53 | int i; 54 | 55 | memset(k_ipad, 0, sizeof k_ipad); 56 | memset(k_opad, 0, sizeof k_opad); 57 | memcpy(k_ipad, key, key_len); 58 | memcpy(k_opad, key, key_len); 59 | 60 | for (i = 0; i < 64; i++) 61 | { 62 | k_ipad[i] ^= 0x36; 63 | k_opad[i] ^= 0x5c; 64 | } 65 | 66 | SHA1_Init(&context); 67 | SHA1_Update(&context, k_ipad, 64); 68 | SHA1_Update(&context, msg, length); 69 | SHA1_Final(digest, &context); 70 | SHA1_Init(&context); 71 | SHA1_Update(&context, k_opad, 64); 72 | SHA1_Update(&context, digest, SHA1_SIZE); 73 | SHA1_Final(digest, &context); 74 | } 75 | 76 | // from http://hardwarefun.com/tutorials/url-encoding-in-arduino 77 | // modified by chaeplin 78 | String esp8266Twitter::URLEncode(const char* msg) 79 | { 80 | const char *hex = "0123456789ABCDEF"; 81 | String encodedMsg = ""; 82 | 83 | while (*msg != '\0') 84 | { 85 | if ( ('a' <= *msg && *msg <= 'z') 86 | || ('A' <= *msg && *msg <= 'Z') 87 | || ('0' <= *msg && *msg <= '9') 88 | || *msg == '-' || *msg == '_' || *msg == '.' || *msg == '~' ) 89 | { 90 | encodedMsg += *msg; 91 | } 92 | else 93 | { 94 | encodedMsg += '%'; 95 | encodedMsg += hex[*msg >> 4]; 96 | encodedMsg += hex[*msg & 0xf]; 97 | } 98 | msg++; 99 | } 100 | return encodedMsg; 101 | } 102 | 103 | String esp8266Twitter::make_signature(const char* secret_one, const char* secret_two, String base_string) 104 | { 105 | String signing_key = URLEncode(secret_one); 106 | signing_key += "&"; 107 | signing_key += URLEncode(secret_two); 108 | 109 | uint8_t digestkey[32]; 110 | SHA1_CTX context; 111 | SHA1_Init(&context); 112 | SHA1_Update(&context, (uint8_t*) signing_key.c_str(), (int)signing_key.length()); 113 | SHA1_Final(digestkey, &context); 114 | 115 | uint8_t digest[32]; 116 | ssl_hmac_sha1((uint8_t*) base_string.c_str(), (int)base_string.length(), digestkey, SHA1_SIZE, digest); 117 | 118 | String oauth_signature = URLEncode(base64::encode(digest, SHA1_SIZE).c_str()); 119 | 120 | return oauth_signature; 121 | } 122 | 123 | bool esp8266Twitter::do_http_text_post(String OAuth_header) 124 | { 125 | String payload = ""; 126 | String uri_to_post = BASE_URI; 127 | String req_body_to_post; 128 | 129 | req_body_to_post = "status="; 130 | req_body_to_post += String(URLEncode(this->value_status)); 131 | 132 | HTTPClient http; 133 | http.begin(BASE_HOST, HTTPSPORT, uri_to_post, api_fingerprint); 134 | http.addHeader("Authorization", OAuth_header); 135 | http.addHeader("Content-Length", String(req_body_to_post.length())); 136 | http.addHeader("Content-Type", "application/x-www-form-urlencoded"); 137 | int httpCode = http.POST(req_body_to_post); 138 | 139 | // debug 140 | Serial.print("[DEBUG] do_http_text_post httpCode : "); 141 | Serial.println(httpCode); 142 | 143 | 144 | if (httpCode > 0) 145 | { 146 | //if (httpCode >= 200 && httpCode < 400) { 147 | payload = http.getString(); 148 | Serial.print("[DEBUG] do_http_text_post payload : "); 149 | Serial.println(payload); 150 | //} 151 | } 152 | else 153 | { 154 | http.end(); 155 | return false; 156 | } 157 | 158 | http.end(); 159 | 160 | if (httpCode >= 200 && httpCode < 400) 161 | { 162 | return true; 163 | } 164 | else 165 | { 166 | return false; 167 | } 168 | } 169 | 170 | String esp8266Twitter::make_OAuth_header(String oauth_signature) 171 | { 172 | String OAuth_header = "OAuth "; 173 | OAuth_header += KEY_CONSUMER_KEY; 174 | OAuth_header += "=\""; 175 | OAuth_header += this->consumerkey; 176 | OAuth_header += "\", "; 177 | OAuth_header += KEY_NONCE; 178 | OAuth_header += "=\""; 179 | OAuth_header += this->value_nonce; 180 | OAuth_header += "\", "; 181 | OAuth_header += KEY_SIGNATURE; 182 | OAuth_header += "=\""; 183 | OAuth_header += oauth_signature; 184 | OAuth_header += "\", "; 185 | OAuth_header += KEY_SIGNATURE_METHOD; 186 | OAuth_header += "=\""; 187 | OAuth_header += VALUE_SIGNATURE_METHOD; 188 | OAuth_header += "\", "; 189 | OAuth_header += KEY_TIMESTAMP; 190 | OAuth_header += "=\""; 191 | OAuth_header += this->value_timestamp; 192 | OAuth_header += "\", "; 193 | OAuth_header += KEY_TOKEN; 194 | OAuth_header += "=\""; 195 | OAuth_header += this->accesstoken; 196 | OAuth_header += "\", "; 197 | OAuth_header += KEY_VERSION; 198 | OAuth_header += "=\""; 199 | OAuth_header += VALUE_VERSION; 200 | OAuth_header += "\""; 201 | 202 | return OAuth_header; 203 | } 204 | 205 | String esp8266Twitter::make_signature(String base_string) 206 | { 207 | String signing_key = URLEncode(this->consumersecret); 208 | signing_key += "&"; 209 | signing_key += URLEncode(this->accessscecret); 210 | 211 | uint8_t digestkey[32]; 212 | SHA1_CTX context; 213 | SHA1_Init(&context); 214 | SHA1_Update(&context, (uint8_t*) signing_key.c_str(), (int)signing_key.length()); 215 | SHA1_Final(digestkey, &context); 216 | 217 | uint8_t digest[32]; 218 | ssl_hmac_sha1((uint8_t*) base_string.c_str(), (int)base_string.length(), digestkey, SHA1_SIZE, digest); 219 | 220 | String oauth_signature = URLEncode(base64::encode(digest, SHA1_SIZE).c_str()); 221 | 222 | return oauth_signature; 223 | } 224 | 225 | String esp8266Twitter::make_base_string(String para_string) 226 | { 227 | String base_string = KEY_HTTP_METHOD; 228 | base_string += "&"; 229 | base_string += URLEncode(BASE_URL); 230 | base_string += "&"; 231 | base_string += URLEncode(para_string.c_str()); 232 | 233 | return base_string; 234 | } 235 | 236 | String esp8266Twitter::make_para_string() 237 | { 238 | String para_string; 239 | para_string += KEY_CONSUMER_KEY; 240 | para_string += "=" ; 241 | para_string += this->consumerkey; 242 | para_string += "&"; 243 | para_string += KEY_NONCE; 244 | para_string += "="; 245 | para_string += this->value_nonce; 246 | para_string += "&"; 247 | para_string += KEY_SIGNATURE_METHOD; 248 | para_string += "="; 249 | para_string += VALUE_SIGNATURE_METHOD; 250 | para_string += "&"; 251 | para_string += KEY_TIMESTAMP; 252 | para_string += "="; 253 | para_string += this->value_timestamp; 254 | para_string += "&"; 255 | para_string += KEY_TOKEN; 256 | para_string += "="; 257 | para_string += this->accesstoken; 258 | para_string += "&"; 259 | para_string += KEY_VERSION; 260 | para_string += "="; 261 | para_string += VALUE_VERSION; 262 | para_string += "&"; 263 | para_string += KEY_STATUS; 264 | para_string += "="; 265 | para_string += URLEncode(this->value_status); 266 | 267 | return para_string; 268 | } 269 | 270 | esp8266Twitter& esp8266Twitter::setKeys(const char * CONSUMER_KEY, const char * CONSUMER_SECRET, const char * ACCESS_TOKEN, const char * ACCESS_SECRET) 271 | { 272 | this->consumerkey = CONSUMER_KEY; 273 | this->consumersecret = CONSUMER_SECRET; 274 | this->accesstoken = ACCESS_TOKEN; 275 | this->accessscecret = ACCESS_SECRET; 276 | return *this; 277 | } 278 | 279 | // end of esp8266Twitter.cpp 280 | --------------------------------------------------------------------------------