From 7fec9e0de7600dddc4e65355a1a2e061be68638a Mon Sep 17 00:00:00 2001 From: anun Date: Mon, 15 Aug 2016 16:49:07 +0700 Subject: [PATCH 1/6] fix error connect server wdt reset --- MicroGear.cpp | 336 ++++++++++++++++++++++++++------------------------ 1 file changed, 173 insertions(+), 163 deletions(-) diff --git a/MicroGear.cpp b/MicroGear.cpp index 30ee2bc..e76dc6d 100644 --- a/MicroGear.cpp +++ b/MicroGear.cpp @@ -102,18 +102,19 @@ void MicroGear::initEndpoint(Client *client, char* endpoint) { char pstr[100]; int port = this->securemode?GEARAUTHSECUREPORT:GEARAUTHPORT; - client->connect(GEARAUTHHOST,port); - sprintf(pstr,"GET /api/endpoint/%s HTTP/1.1\r\n\r\n",this->gearkey); - client->write((const uint8_t *)pstr,strlen(pstr)); - - delay(1000); - getHTTPReply(client,pstr,200); - - if (strlen(pstr)>6) { - strcpy(endpoint,pstr+6); - writeEEPROM(endpoint,EEPROM_ENDPOINTSOFFSET,MAXENDPOINTLENGTH); - } - client->stop(); + if(client->connect(GEARAUTHHOST,port)) { + sprintf(pstr,"GET /api/endpoint/%s HTTP/1.1\r\n\r\n",this->gearkey); + client->write((const uint8_t *)pstr,strlen(pstr)); + + delay(1000); + getHTTPReply(client,pstr,200); + + if (strlen(pstr)>6) { + strcpy(endpoint,pstr+6); + writeEEPROM(endpoint,EEPROM_ENDPOINTSOFFSET,MAXENDPOINTLENGTH); + } + } + client->stop(); } } @@ -123,63 +124,68 @@ void MicroGear::syncTime(Client *client, unsigned long *bts) { char hash[32], hashkey[60]; int port = (this->securemode)?GEARAUTHSECUREPORT:GEARAUTHPORT; - *bts = 0; - client->connect(GEARAUTHHOST,port); - - if (this->securemode) { - WiFiClientSecure *clientsecure = (WiFiClientSecure *)(client); - - // verify a certificate fingerprint against a fingerprint saved in eeprom - readEEPROM(tstr, EEPROM_CERTFINGERPRINT, FINGERPRINTSIZE); - #ifdef DEBUG_H - Serial.print("fingerprint loaded from eeprom : "); - Serial.println(tstr); - #endif - if (clientsecure->verify(tstr, GEARAUTHHOST)) { - #ifdef DEBUG_H - Serial.println("fingerprint matched"); - #endif - } - else { - #ifdef DEBUG_H - Serial.println("fingerprint mismatched, going to update"); - #endif - AuthClient::randomString(nonce,8); - sprintf(tstr,"GET /api/fingerprint/%s/%s HTTP/1.1\r\n\r\n",this->gearkey,nonce); - clientsecure->write((const uint8_t *)tstr,strlen(tstr)); - delay(800); - getHTTPReply(clientsecure,tstr,200); - tstr[FINGERPRINTSIZE-1] = '\0'; // split fingerprint and signature - sprintf(hashkey,"%s&%s&%s",this->gearkey,this->gearsecret,nonce); - Sha1.initHmac((uint8_t*)hashkey,strlen(hashkey)); - Sha1.HmacBase64(hash, tstr); - for (int i=0;istop(); - delay(5000); - return; - } - } + *bts = 0; + if(client->connect(GEARAUTHHOST,port)) { + #ifdef DEBUG_H + Serial.println("connect gearauth"); + #endif + if (this->securemode) { + WiFiClientSecure *clientsecure = (WiFiClientSecure *)(client); + + // verify a certificate fingerprint against a fingerprint saved in eeprom + readEEPROM(tstr, EEPROM_CERTFINGERPRINT, FINGERPRINTSIZE); + #ifdef DEBUG_H + Serial.print("fingerprint loaded from eeprom : "); + Serial.println(tstr); + #endif + if (clientsecure->verify(tstr, GEARAUTHHOST)) { + #ifdef DEBUG_H + Serial.println("fingerprint matched"); + #endif + } + else { + #ifdef DEBUG_H + Serial.println("fingerprint mismatched, going to update"); + #endif + AuthClient::randomString(nonce,8); + sprintf(tstr,"GET /api/fingerprint/%s/%s HTTP/1.1\r\n\r\n",this->gearkey,nonce); + clientsecure->write((const uint8_t *)tstr,strlen(tstr)); + delay(800); + getHTTPReply(clientsecure,tstr,200); + tstr[FINGERPRINTSIZE-1] = '\0'; // split fingerprint and signature + sprintf(hashkey,"%s&%s&%s",this->gearkey,this->gearsecret,nonce); + Sha1.initHmac((uint8_t*)hashkey,strlen(hashkey)); + Sha1.HmacBase64(hash, tstr); + for (int i=0;istop(); + delay(5000); + return; + } + } + } + strcpy(tstr,"GET /api/time HTTP/1.1\r\n\r\n"); + client->write((const uint8_t *)tstr,strlen(tstr)); + + delay(1000); + getHTTPReply(client,tstr,200); + *bts = atol(tstr) - millis()/1000; + client->stop(); } - - strcpy(tstr,"GET /api/time HTTP/1.1\r\n\r\n"); - client->write((const uint8_t *)tstr,strlen(tstr)); - - delay(1000); - getHTTPReply(client,tstr,200); - *bts = atol(tstr) - millis()/1000; - client->stop(); + #ifdef DEBUG_H + Serial.println("synctime done"); + #endif } MicroGear::MicroGear(Client& netclient ) { @@ -259,19 +265,20 @@ void MicroGear::resetToken() { char revokecode[REVOKECODESIZE+1]; int port = this->securemode?GEARAUTHSECUREPORT:GEARAUTHPORT; - sockclient->connect(GEARAUTHHOST,port); - readEEPROM(token,EEPROM_TOKENOFFSET,TOKENSIZE); - readEEPROM(revokecode,EEPROM_REVOKECODEOFFSET,REVOKECODESIZE); - sprintf(pstr,"GET /api/revoke/%s/%s HTTP/1.1\r\n\r\n",token,revokecode); - sockclient->write((const uint8_t *)pstr,strlen(pstr)); - - delay(1000); - getHTTPReply(sockclient,pstr,200); - - if (strcmp(pstr,"FAILED")!=0) { - *state = EEPROM_STATE_NUL; - writeEEPROM(state,EEPROM_STATEOFFSET,1); - } + if(sockclient->connect(GEARAUTHHOST,port)) { + readEEPROM(token,EEPROM_TOKENOFFSET,TOKENSIZE); + readEEPROM(revokecode,EEPROM_REVOKECODEOFFSET,REVOKECODESIZE); + sprintf(pstr,"GET /api/revoke/%s/%s HTTP/1.1\r\n\r\n",token,revokecode); + sockclient->write((const uint8_t *)pstr,strlen(pstr)); + + delay(1000); + getHTTPReply(sockclient,pstr,200); + + if (strcmp(pstr,"FAILED")!=0) { + *state = EEPROM_STATE_NUL; + writeEEPROM(state,EEPROM_STATEOFFSET,1); + } + } sockclient->stop(); } else { @@ -347,6 +354,7 @@ void MicroGear::getToken(char *gkey, char *galias, char* token, char* tokensecre Serial.println("authclient is disconnected"); #endif delay(2000); + return false; } } while (!authstatus); } @@ -376,6 +384,7 @@ void MicroGear::getToken(char *gkey, char *galias, char* token, char* tokensecre #endif authclient->stop(); delay(1000); + break; } } #ifdef DEBUG_H @@ -463,94 +472,95 @@ bool MicroGear::connectBroker(char* appid) { char endpoint[MAXENDPOINTLENGTH+1]; int gbport; - do { - syncTime(sockclient, &bootts); - } while (bootts == 0); + syncTime(sockclient, &bootts); #ifdef DEBUG_H Serial.print("Time stamp : "); Serial.println(bootts); #endif - this->appid = appid; - topicprefixlen = strlen(appid)+1; - - if (mqttclient) { - // recently disconnected with code 4 - if (mqttclient->state() == 4) { - resetToken(); - } - delete(mqttclient); - } - - if (authclient) delete(authclient); - authclient = new AuthClient(*sockclient); - authclient->init(appid,scope,bootts); - getToken(this->gearkey,this->gearalias,token,tokensecret,endpoint); - delete(authclient); - authclient = NULL; - - /* if endpoint is empty, request a new one */ - initEndpoint(sockclient, endpoint); - - /* generate one-time user/password */ - sprintf(username,"%s%%%s%%%lu",token,gearkey,bootts+millis()/1000); - sprintf(buff,"%s&%s",tokensecret,gearsecret); - Sha1.initHmac((uint8_t*)buff,strlen(buff)); - Sha1.HmacBase64(password, username); - - if (*token && *tokensecret) { - #ifdef DEBUG_H - Serial.println("Going to connect to MQTT broker"); - Serial.println(token); - Serial.println(username); - Serial.println(password); - Serial.println(endpoint); - #endif - - char *p = endpoint; - while (*p!='\0') { - if (*p == ':') { - *p = '\0'; - p++; - break; - } - p++; - } - - gbport = this->securemode?GBSECUREPORT:GBPORT; - mqttclient = new PubSubClient(endpoint, gbport, msgCallback, *sockclient); - #ifdef DEBUG_H - Serial.print("Connecting to : "); - Serial.print(endpoint); - Serial.print(":"); - Serial.println(gbport); - #endif - delay(500); - - constate = this->mqttclient->connect(token,username+TOKENSIZE+1,password); - switch (constate) { - case CLIENT_CONNECTED : - backoff = MINBACKOFFTIME; - if (cb_present) - subscribe("/&present"); - if (cb_absent) - subscribe("/&absent"); - - sprintf(buff,"/&id/%s/#",token); - subscribe(buff); - - if (cb_connected) - cb_connected(NULL,NULL,0); - break; - case CLIENT_NOTCONNECT : - if (backoff < MAXBACKOFFTIME) backoff = 2*backoff; - delay(backoff); - break; - } - return constate; - } - else return false; + if(bootts!=0){ + this->appid = appid; + topicprefixlen = strlen(appid)+1; + + if (mqttclient) { + // recently disconnected with code 4 + if (mqttclient->state() == 4) { + resetToken(); + } + delete(mqttclient); + } + + if (authclient) delete(authclient); + authclient = new AuthClient(*sockclient); + authclient->init(appid,scope,bootts); + getToken(this->gearkey,this->gearalias,token,tokensecret,endpoint); + delete(authclient); + authclient = NULL; + + /* if endpoint is empty, request a new one */ + initEndpoint(sockclient, endpoint); + + /* generate one-time user/password */ + sprintf(username,"%s%%%s%%%lu",token,gearkey,bootts+millis()/1000); + sprintf(buff,"%s&%s",tokensecret,gearsecret); + Sha1.initHmac((uint8_t*)buff,strlen(buff)); + Sha1.HmacBase64(password, username); + + if (*token && *tokensecret) { + #ifdef DEBUG_H + Serial.println("Going to connect to MQTT broker"); + Serial.println(token); + Serial.println(username); + Serial.println(password); + Serial.println(endpoint); + #endif + + char *p = endpoint; + while (*p!='\0') { + if (*p == ':') { + *p = '\0'; + p++; + break; + } + p++; + } + + gbport = this->securemode?GBSECUREPORT:GBPORT; + mqttclient = new PubSubClient(endpoint, gbport, msgCallback, *sockclient); + #ifdef DEBUG_H + Serial.print("Connecting to : "); + Serial.print(endpoint); + Serial.print(":"); + Serial.println(gbport); + #endif + delay(500); + + constate = this->mqttclient->connect(token,username+TOKENSIZE+1,password); + switch (constate) { + case CLIENT_CONNECTED : + backoff = MINBACKOFFTIME; + if (cb_present) + subscribe("/&present"); + if (cb_absent) + subscribe("/&absent"); + + sprintf(buff,"/&id/%s/#",token); + subscribe(buff); + + if (cb_connected) + cb_connected(NULL,NULL,0); + break; + case CLIENT_NOTCONNECT : + if (backoff < MAXBACKOFFTIME) backoff = 2*backoff; + delay(backoff); + break; + } + return constate; + } + else return false; + } + else return false; } void MicroGear::useTLS(bool usetls) { From 448b14317c3e581964fbe378c6a1322f5c97bc6e Mon Sep 17 00:00:00 2001 From: anun Date: Wed, 17 Aug 2016 19:00:32 +0700 Subject: [PATCH 2/6] fix code error --- MicroGear.cpp | 240 +++++++++++++++++++++++++------------------------- 1 file changed, 119 insertions(+), 121 deletions(-) diff --git a/MicroGear.cpp b/MicroGear.cpp index e76dc6d..29f97a8 100644 --- a/MicroGear.cpp +++ b/MicroGear.cpp @@ -38,32 +38,30 @@ void msgCallback(char* topic, uint8_t* payload, unsigned int length) { bool MicroGear::clientReadln(Client* client, char *buffer, size_t buflen) { size_t pos = 0; + while (true) { - while (true) { - uint8_t byte = client->read(); - if (byte == '\n') { - // EOF found. - if (pos < buflen) { - if (pos > 0 && buffer[pos - 1] == '\r') - pos--; - buffer[pos] = '\0'; - } - else { - buffer[buflen - 1] = '\0'; - } - return true; + uint8_t byte = client->read(); + if (byte == '\n') { + // EOF found. + if (pos < buflen) { + if (pos > 0 && buffer[pos - 1] == '\r') + pos--; + buffer[pos] = '\0'; } - - if (byte != 255) { - if (pos < buflen) buffer[pos++] = byte; + else { + buffer[buflen - 1] = '\0'; } - else{ - buffer[pos++] = '\0'; - return true; - } + return true; } + + if (byte != 255) { + if (pos < buflen) buffer[pos++] = byte; + } + else{ + buffer[pos++] = '\0'; + return false; + } } - return false; } int MicroGear::getHTTPReply(Client *client, char *buff, size_t buffsize) { @@ -102,7 +100,7 @@ void MicroGear::initEndpoint(Client *client, char* endpoint) { char pstr[100]; int port = this->securemode?GEARAUTHSECUREPORT:GEARAUTHPORT; - if(client->connect(GEARAUTHHOST,port)) { + if(client->connect(GEARAUTHHOST,port)){ sprintf(pstr,"GET /api/endpoint/%s HTTP/1.1\r\n\r\n",this->gearkey); client->write((const uint8_t *)pstr,strlen(pstr)); @@ -113,8 +111,8 @@ void MicroGear::initEndpoint(Client *client, char* endpoint) { strcpy(endpoint,pstr+6); writeEEPROM(endpoint,EEPROM_ENDPOINTSOFFSET,MAXENDPOINTLENGTH); } + client->stop(); } - client->stop(); } } @@ -124,11 +122,9 @@ void MicroGear::syncTime(Client *client, unsigned long *bts) { char hash[32], hashkey[60]; int port = (this->securemode)?GEARAUTHSECUREPORT:GEARAUTHPORT; - *bts = 0; - if(client->connect(GEARAUTHHOST,port)) { - #ifdef DEBUG_H - Serial.println("connect gearauth"); - #endif + *bts = 0; + if(client->connect(GEARAUTHHOST,port)){ + if (this->securemode) { WiFiClientSecure *clientsecure = (WiFiClientSecure *)(client); @@ -175,6 +171,7 @@ void MicroGear::syncTime(Client *client, unsigned long *bts) { } } } + strcpy(tstr,"GET /api/time HTTP/1.1\r\n\r\n"); client->write((const uint8_t *)tstr,strlen(tstr)); @@ -182,15 +179,12 @@ void MicroGear::syncTime(Client *client, unsigned long *bts) { getHTTPReply(client,tstr,200); *bts = atol(tstr) - millis()/1000; client->stop(); - } - #ifdef DEBUG_H - Serial.println("synctime done"); - #endif + } } MicroGear::MicroGear(Client& netclient ) { sockclient = &netclient; - constate = CLIENT_NOTCONNECT; + constate = MQTTCLIENT_NOTCONNECTED; authclient = NULL; mqttclient = NULL; @@ -265,7 +259,7 @@ void MicroGear::resetToken() { char revokecode[REVOKECODESIZE+1]; int port = this->securemode?GEARAUTHSECUREPORT:GEARAUTHPORT; - if(sockclient->connect(GEARAUTHHOST,port)) { + if(sockclient->connect(GEARAUTHHOST,port)){ readEEPROM(token,EEPROM_TOKENOFFSET,TOKENSIZE); readEEPROM(revokecode,EEPROM_REVOKECODEOFFSET,REVOKECODESIZE); sprintf(pstr,"GET /api/revoke/%s/%s HTTP/1.1\r\n\r\n",token,revokecode); @@ -278,8 +272,8 @@ void MicroGear::resetToken() { *state = EEPROM_STATE_NUL; writeEEPROM(state,EEPROM_STATEOFFSET,1); } + sockclient->stop(); } - sockclient->stop(); } else { *state = EEPROM_STATE_NUL; @@ -289,7 +283,7 @@ void MicroGear::resetToken() { } -void MicroGear::getToken(char *gkey, char *galias, char* token, char* tokensecret, char *endpoint) { +bool MicroGear::getToken(char *gkey, char *galias, char* token, char* tokensecret, char *endpoint) { char state[2], tstate[2]; int authstatus = 0; @@ -353,7 +347,7 @@ void MicroGear::getToken(char *gkey, char *galias, char* token, char* tokensecre #ifdef DEBUG_H Serial.println("authclient is disconnected"); #endif - delay(2000); + //delay(2000); return false; } } while (!authstatus); @@ -440,7 +434,7 @@ void MicroGear::getToken(char *gkey, char *galias, char* token, char* tokensecre } } }while (*state == EEPROM_STATE_REQ); - // reset accesstoken retry counter + // reset accesstoken retry counter retry = RETRY; #ifdef DEBUG_H Serial.println(authstatus); Serial.println(token); Serial.println(tokensecret); Serial.println(endpoint); @@ -453,17 +447,20 @@ void MicroGear::getToken(char *gkey, char *galias, char* token, char* tokensecre readEEPROM(tokensecret,EEPROM_TOKENSECRETOFFSET,TOKENSECRETSIZE); readEEPROM(endpoint,EEPROM_ENDPOINTSOFFSET,MAXENDPOINTLENGTH); } + + authclient->stop(); if (*state != EEPROM_STATE_ACC) { #ifdef DEBUG_H Serial.println("Fail to get a token."); #endif - delay(2000); + //delay(2000); + return false; } - authclient->stop(); + return true; } -bool MicroGear::connectBroker(char* appid) { +int MicroGear::connectBroker(char* appid) { char username[USERNAMESIZE+1]; char password[PASSWORDSIZE+1]; char buff[2*TOKENSECRETSIZE+2]; @@ -471,6 +468,7 @@ bool MicroGear::connectBroker(char* appid) { char tokensecret[TOKENSECRETSIZE+1]; char endpoint[MAXENDPOINTLENGTH+1]; int gbport; + bool tokenOK; syncTime(sockclient, &bootts); @@ -479,96 +477,96 @@ bool MicroGear::connectBroker(char* appid) { Serial.println(bootts); #endif - if(bootts!=0){ - this->appid = appid; - topicprefixlen = strlen(appid)+1; + this->appid = appid; + topicprefixlen = strlen(appid)+1; - if (mqttclient) { - // recently disconnected with code 4 - if (mqttclient->state() == 4) { - resetToken(); - } - delete(mqttclient); - } + if (mqttclient) { + // recently disconnected with code 4 + if (mqttclient->state() == 4) { + resetToken(); + } + delete(mqttclient); + } - if (authclient) delete(authclient); - authclient = new AuthClient(*sockclient); - authclient->init(appid,scope,bootts); - getToken(this->gearkey,this->gearalias,token,tokensecret,endpoint); - delete(authclient); - authclient = NULL; - - /* if endpoint is empty, request a new one */ - initEndpoint(sockclient, endpoint); - - /* generate one-time user/password */ - sprintf(username,"%s%%%s%%%lu",token,gearkey,bootts+millis()/1000); - sprintf(buff,"%s&%s",tokensecret,gearsecret); - Sha1.initHmac((uint8_t*)buff,strlen(buff)); - Sha1.HmacBase64(password, username); - - if (*token && *tokensecret) { - #ifdef DEBUG_H - Serial.println("Going to connect to MQTT broker"); - Serial.println(token); - Serial.println(username); - Serial.println(password); - Serial.println(endpoint); - #endif + if (authclient) delete(authclient); + authclient = new AuthClient(*sockclient); + authclient->init(appid,scope,bootts); + + tokenOK = getToken(this->gearkey,this->gearalias,token,tokensecret,endpoint); + delete(authclient); + authclient = NULL; + + if (tokenOK && *token && *tokensecret) { - char *p = endpoint; - while (*p!='\0') { - if (*p == ':') { - *p = '\0'; - p++; - break; - } - p++; - } + /* if endpoint is empty, request a new one */ + initEndpoint(sockclient, endpoint); - gbport = this->securemode?GBSECUREPORT:GBPORT; - mqttclient = new PubSubClient(endpoint, gbport, msgCallback, *sockclient); - #ifdef DEBUG_H - Serial.print("Connecting to : "); - Serial.print(endpoint); - Serial.print(":"); - Serial.println(gbport); - #endif - delay(500); - - constate = this->mqttclient->connect(token,username+TOKENSIZE+1,password); - switch (constate) { - case CLIENT_CONNECTED : - backoff = MINBACKOFFTIME; - if (cb_present) - subscribe("/&present"); - if (cb_absent) - subscribe("/&absent"); - - sprintf(buff,"/&id/%s/#",token); - subscribe(buff); - - if (cb_connected) - cb_connected(NULL,NULL,0); - break; - case CLIENT_NOTCONNECT : - if (backoff < MAXBACKOFFTIME) backoff = 2*backoff; - delay(backoff); - break; - } - return constate; - } - else return false; - } - else return false; + /* generate one-time user/password */ + sprintf(username,"%s%%%s%%%lu",token,gearkey,bootts+millis()/1000); + sprintf(buff,"%s&%s",tokensecret,gearsecret); + Sha1.initHmac((uint8_t*)buff,strlen(buff)); + Sha1.HmacBase64(password, username); + + #ifdef DEBUG_H + Serial.println("Going to connect to MQTT broker"); + Serial.println(token); + Serial.println(username); + Serial.println(password); + Serial.println(endpoint); + #endif + + char *p = endpoint; + while (*p!='\0') { + if (*p == ':') { + *p = '\0'; + p++; + break; + } + p++; + } + + gbport = this->securemode?GBSECUREPORT:GBPORT; + mqttclient = new PubSubClient(endpoint, gbport, msgCallback, *sockclient); + #ifdef DEBUG_H + Serial.print("Connecting to : "); + Serial.print(endpoint); + Serial.print(":"); + Serial.println(gbport); + #endif + delay(500); + + constate = this->mqttclient->connect(token,username+TOKENSIZE+1,password); + switch (constate) { + case MQTTCLIENT_CONNECTED : + backoff = MINBACKOFFTIME; + if (cb_present) + subscribe("/&present"); + if (cb_absent) + subscribe("/&absent"); + + sprintf(buff,"/&id/%s/#",token); + subscribe(buff); + + if (cb_connected) + cb_connected(NULL,NULL,0); + + return NETPIECLIENT_CONNECTED; + + case MQTTCLIENT_NOTCONNECTED : + if (backoff < MAXBACKOFFTIME) backoff = 2*backoff; + delay(backoff); + return NETPIECLIENT_NOTCONNECTED; + } + } + else return NETPIECLIENT_TOKENERROR; } void MicroGear::useTLS(bool usetls) { this->securemode = usetls; } -bool MicroGear::connect(char* appid) { - connectBroker(appid); +int MicroGear::connect(char* appid) { + return connectBroker(appid); } bool MicroGear::connected() { From df4f42a4e29c6fc985fbb6d9662fac1e1028f0ed Mon Sep 17 00:00:00 2001 From: chavee Date: Mon, 6 Mar 2017 13:51:12 +0700 Subject: [PATCH 3/6] add docs directory --- docs/images/EEPROM-draw.io.png | Bin 0 -> 13311 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/images/EEPROM-draw.io.png diff --git a/docs/images/EEPROM-draw.io.png b/docs/images/EEPROM-draw.io.png new file mode 100644 index 0000000000000000000000000000000000000000..f05d79c6b349156ff07a6929abc1a7a5e69c8b22 GIT binary patch literal 13311 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 Date: Mon, 6 Mar 2017 14:03:47 +0700 Subject: [PATCH 4/6] rename diagram image --- ...{EEPROM-draw.io.png => EEPROM-token-diagram.png} | Bin 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/images/{EEPROM-draw.io.png => EEPROM-token-diagram.png} (100%) diff --git a/docs/images/EEPROM-draw.io.png b/docs/images/EEPROM-token-diagram.png similarity index 100% rename from docs/images/EEPROM-draw.io.png rename to docs/images/EEPROM-token-diagram.png From a5c314cb6519169c41df6181c094e493b0259a76 Mon Sep 17 00:00:00 2001 From: Chavee Issariyapat Date: Mon, 6 Mar 2017 14:04:50 +0700 Subject: [PATCH 5/6] Update README.md --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.md b/README.md index e39abe2..c78a4ea 100644 --- a/README.md +++ b/README.md @@ -160,6 +160,17 @@ microgear.init("sXfqDcXHzbFXiLk", "DNonzg2ivwS8ceksykGntrfQjxbL98", "myplant"); --- +**void MicroGear:: setEEPROMOffset(int offset)** + +Shift the offset of an EEPROM address where a microgear token is stored. This command will be useful if your application wants to store some other data in an EEPROM as well. The default offset value is 0. + +![EEPROM-token](docs/images/EEPROM-token-diagram.png) + +**arguments** +* *offset* - The EEPROM address offset vale. The default is 0. + +--- + **void MicroGear::on(unsigned char event, void (* callback)(char*, uint8_t*,unsigned int))** Add a callback listener to the event. From 6e71b798f94442c4095d548cc4d2c14debcb168e Mon Sep 17 00:00:00 2001 From: Chavee Issariyapat Date: Mon, 6 Mar 2017 14:06:07 +0700 Subject: [PATCH 6/6] Update README.th.md --- README.th.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.th.md b/README.th.md index 7166b10..003feec 100644 --- a/README.th.md +++ b/README.th.md @@ -153,6 +153,17 @@ microgear.init("sXfqDcXHzbFXiLk", "DNonzg2ivwS8ceksykGntrfQjxbL98", "myplant"); --- +**void MicroGear:: setEEPROMOffset(int *offset*)** + +ตั้งค่าตำแหน่งแรกของ EEPROM ที่จะให้ microgear เก็บบันทึก token คำสั่งนี้จะมีประโยชน์ในกรณีที่ผู้ใช้ ต้องการใช้ EEPROM ในการเก็บบันทึกข้อมูลอย่างขึ้นด้วย ข้อมูลจะได้ไม่บันทึกทับซ้อนกัน โดยปกติหากไม่ได้เรียกคำสั่งนี้ microgear library จะใช้ EEPROM เริ่มต้นที่ตำแหน่งที่ 0 ในการเก็บ token + +![EEPROM-token](docs/images/EEPROM-token-diagram.png) + +**arguments** +* *offset* - ค่า offset ของตำแหน่ง EEPROM ที่ microgaer ใช้บันทึกข้อมูล ค่า default เป็น 0 + +--- + **void MicroGear::on(unsigned char event, void (* callback)(char*, uint8_t*,unsigned int))** เพิ่มฟังก์ชั่นที่ตอบสนองต่อ event