Skip to content

Commit 6adbcfa

Browse files
committed
include bc95udp as a part of microgear library
1 parent b0ee70d commit 6adbcfa

11 files changed

+2013
-0
lines changed

BC95.cpp

+280
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,280 @@
1+
/*
2+
BC95 adapter class for Arduino.
3+
Author: Chavee Issariyapat
4+
5+
6+
This software is released under the MIT License.
7+
*/
8+
9+
#include "BC95.h"
10+
11+
#if BC95_USE_EXTERNAL_BUFFER == 1
12+
char *buffer = NULL;
13+
size_t buffersize = 0;
14+
#else
15+
char buffer[BC95_BUFFER_SIZE];
16+
#define buffersize c
17+
#endif
18+
19+
const char STOPPER[][STOPPERLEN] = {END_LINE, END_OK, END_ERROR};
20+
21+
#define COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
22+
#define STOPPERCOUNT COUNT_OF(STOPPER)
23+
24+
#if BC95_USE_EXTERNAL_BUFFER == 1
25+
void BC95Class::setExternalBuffer(char *sbuffer, size_t sbuffersize) {
26+
buffer = sbuffer;
27+
buffersize = sbuffersize;
28+
}
29+
#endif
30+
31+
void BC95Class::begin(Stream &serial) {
32+
BC95Serial = &serial;
33+
memset(socketpool, 0, sizeof(SOCKD)*MAXSOCKET);
34+
}
35+
36+
char* BC95Class::fetchSocketPacket(SOCKD *socket, uint16_t len) {
37+
char *p;
38+
if((p = getSerialResponse("\x0D\x0A", 0))) return p;
39+
40+
cmdPrint(F("AT+NSORF="));
41+
cmdPrint(socket->sockid);
42+
cmdPrint(",");
43+
cmdPrintln(len);
44+
45+
p = getSerialResponse("\x0D\x0A");
46+
return p;
47+
}
48+
49+
// return a null-terminated response text from AT-command
50+
char* BC95Class::getSerialResponse(char *prefix) {
51+
return getSerialResponse(prefix, BC95_DEFAULT_SERIAL_TIMEOUT);
52+
}
53+
54+
char* BC95Class::getSerialResponse(char *prefix, uint32_t timeout) {
55+
56+
if (readUntilDone(buffer, timeout, buffersize) >= 0) {
57+
char *p,*r;
58+
uint8_t sno;
59+
size_t plen;
60+
61+
p = strstr((const char *)buffer, "+NSONMI:");
62+
if (p != NULL) {
63+
#ifdef LOG_DEBUG
64+
Serial.println(p);
65+
#endif
66+
67+
p = p+8; // skip +NSONMI:
68+
plen = 0;
69+
for (r=p+2; *r>='0' && *r<='9'; r++) {
70+
plen = 10*plen + *r-'0';
71+
}
72+
sno = (unsigned char)*p - '0';
73+
if (sno>=0 && sno<MAXSOCKET)
74+
socketpool[sno].bc95_msglen = plen;
75+
76+
// if +NSONMI is unexpectly found, read serial again
77+
if (readUntilDone(buffer, timeout, buffersize) >= 0) {
78+
return parseResponse(buffer, prefix);
79+
}
80+
else {
81+
return NULL;
82+
}
83+
}
84+
else {
85+
#ifdef LOG_DEBUG
86+
Serial.print("Incoming data : ");
87+
Serial.println(buffer);
88+
#endif
89+
return parseResponse(buffer, prefix);
90+
}
91+
}
92+
else {
93+
return NULL;
94+
}
95+
}
96+
97+
// parse text with a prefix
98+
char* BC95Class::parseResponse(char *rawstr, char* pref) {
99+
uint8_t i;
100+
char *r, *p;
101+
102+
if (pref==NULL || *pref=='\0') {
103+
return rawstr;
104+
}
105+
p = strstr((const char *)rawstr, (const char *)pref);
106+
if (p != NULL) {
107+
p += strlen(pref);
108+
// skip STOPPER[0]
109+
110+
for (i=1; i<STOPPERCOUNT; i++) {
111+
r = strstr((const char *)p, (const char *)STOPPER[i]);
112+
if (r != NULL) {
113+
*r = '\0';
114+
r += strlen(STOPPER[i]);
115+
return p;
116+
}
117+
}
118+
}
119+
return NULL;
120+
}
121+
122+
int BC95Class::readUntilDone(char* buff, uint32_t timeout, size_t maxsize) {
123+
uint8_t i = 0;
124+
char *p = buff;
125+
int h[STOPPERCOUNT] = {0};
126+
unsigned long starttm = millis();
127+
128+
memset(buff, 0, maxsize);
129+
while(true) {
130+
if (BC95Serial->available()) {
131+
*p = BC95Serial->read();
132+
}
133+
else {
134+
if (millis() - starttm > timeout) {
135+
*p = '\0';
136+
return READ_TIMEOUT;
137+
}
138+
else {
139+
delay(1);
140+
continue;
141+
}
142+
}
143+
144+
for (i=0; i<STOPPERCOUNT; i++) {
145+
if (STOPPER[i][h[i]] != *p) h[i] = 0;
146+
else h[i]++;
147+
148+
if (STOPPER[i][h[i]] == '\0') {
149+
// terminate when END_OK and END_ERROR found. and also when END_LINE found after +NSONMI:
150+
if (i > 0 || (i==0 && strstr(buff, "+NSONMI:")!=NULL)) {
151+
*(p+1) = '\0';
152+
return i;
153+
}
154+
}
155+
if (p - buff > maxsize) {
156+
*(p+1) = '\0';
157+
return READ_OVERFLOW;
158+
}
159+
if (*p == '\0') {
160+
return READ_INCOMPLETE;
161+
}
162+
}
163+
p++;
164+
}
165+
return buff;
166+
}
167+
168+
void BC95Class::reset() {
169+
cmdPrintln(F("AT+NRB"));
170+
delay(2000);
171+
getSerialResponse("REBOOTING");
172+
cmdPrintln(F("AT+CFUN=1"));
173+
delay(2000);
174+
cmdPrintln(F("AT"));
175+
delay(2000);
176+
while(BC95Serial->available() > 0) BC95Serial->read();
177+
}
178+
179+
bool BC95Class::attachNetwork() {
180+
cmdPrintln(F("AT+CGATT=1"));
181+
cmdPrintln(F("AT+CGATT?"));
182+
return getSerialResponse("+CGATT:1");
183+
}
184+
185+
char* BC95Class::getIMEI() {
186+
cmdPrintln(F("AT+CGSN=1"));
187+
return getSerialResponse("+CGSN:");
188+
}
189+
190+
char* BC95Class::getIMSI() {
191+
cmdPrintln(F("AT+CIMI"));
192+
return getSerialResponse("\x0D\x0A");
193+
}
194+
195+
/* This function needs BC95_BUFFER_SIZE > 200 */
196+
char* BC95Class::getManufacturerModel() {
197+
cmdPrintln(F("AT+CGMM"));
198+
return getSerialResponse("\x0D\x0A");
199+
}
200+
201+
char* BC95Class::getManufacturerRevision() {
202+
cmdPrintln(F("AT+CGMR"));
203+
return getSerialResponse("\x0D\x0A");
204+
}
205+
206+
char* BC95Class::getIPAddress() {
207+
cmdPrintln(F("AT+CGPADDR=0"));
208+
return getSerialResponse("+CGPADDR:0,");
209+
}
210+
211+
int8_t BC95Class::getSignalStrength() {
212+
char *p;
213+
int8_t r = 0, i;
214+
cmdPrintln(F("AT+CSQ"));
215+
p = getSerialResponse("+CSQ:");
216+
for (i=0; i<2; i++) {
217+
if (*p>='0' && *p<='9') r=10*r + *p-'0';
218+
p++;
219+
}
220+
return 2*r-113;
221+
}
222+
223+
SOCKD* BC95Class::createSocket(uint16_t port){
224+
uint8_t no;
225+
cmdPrint(F("AT+NSOCR=DGRAM,17,"));
226+
cmdPrint( port );
227+
cmdPrintln(F(",1"));
228+
no = *(getSerialResponse("\x0D\x0A")) - '0';
229+
230+
if (no>=0 && no<MAXSOCKET) {
231+
socketpool[no].sockid = no;
232+
socketpool[no].status = 1;
233+
socketpool[no].port = port;
234+
return &socketpool[no];
235+
}
236+
else {
237+
return NULL;
238+
}
239+
}
240+
241+
int BC95Class::sendPacket(SOCKD *socket, IPAddress destIP, uint16_t destPort, uint8_t *payload, size_t size) {
242+
uint8_t i;
243+
unsigned char *p;
244+
cmdPrint(F("AT+NSOST="));
245+
cmdPrint(socket->sockid);
246+
cmdPrint(",");
247+
cmdPrint(destIP);
248+
cmdPrint(",");
249+
cmdPrint(destPort);
250+
cmdPrint(",");
251+
cmdPrint(size);
252+
cmdPrint(",");
253+
for (p=payload, i=0; i<size; p++,i++) {
254+
if (*p < 16) cmdPrint("0");
255+
cmdPrint(*p, HEX);
256+
}
257+
cmdPrint("\x0D\x0A");
258+
getSerialResponse("\x0D\x0A");
259+
return 1;
260+
}
261+
262+
int BC95Class::sendPacket(SOCKD *socket, IPAddress destIP, uint16_t destPort, char* payload) {
263+
uint8_t len = strlen(payload);
264+
sendPacket(socket, destIP, destPort, payload, len);
265+
}
266+
267+
void BC95Class::closeSocket(SOCKD *socket) {
268+
cmdPrint(F("AT+NSOCL="));
269+
cmdPrintln(socket->sockid);
270+
getSerialResponse("");
271+
socketpool[socket->sockid].status = 0;
272+
}
273+
274+
uint8_t* getBuffer() {
275+
return (uint8_t *)buffer;
276+
}
277+
278+
#if !defined NO_GLOBAL_INSTANCES && !defined NO_GLOBAL_BC95
279+
BC95Class BC95;
280+
#endif

BC95.h

+111
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/*
2+
BC95 adapter class for Arduino.
3+
Author: Chavee Issariyapat
4+
5+
6+
This software is released under the MIT License.
7+
*/
8+
9+
#ifndef BC95_h
10+
#define BC95_h
11+
12+
#include "settings.h"
13+
#include <Arduino.h>
14+
#include <IPAddress.h>
15+
16+
#if BC95_PRINT_DEBUG == 1
17+
#define ECHO_DEBUG
18+
#define LOG_DEBUG
19+
#endif
20+
21+
#define MAXSOCKET 7
22+
23+
#define READ_TIMEOUT -1
24+
#define READ_OVERFLOW -2
25+
#define READ_INCOMPLETE -3
26+
#define STOPPERLEN 12
27+
28+
#define END_LINE "\x0D\x0A"
29+
#define END_OK "\x0D\x0A\x0D\x0A\x4F\x4B\x0D\x0A"
30+
#define END_ERROR "\x0D\x0A\x0D\x0A\x45\x52\x52\x4F\x52\x0D\x0A"
31+
32+
#define CMDPRINTMACRO(_1,_2,NAME,...) NAME
33+
#define cmdPrint(...) CMDPRINTMACRO(__VA_ARGS__, cmdPrint2, cmdPrint1)(__VA_ARGS__)
34+
35+
#define CMDPRINTLNMACRO(_1,_2,NAME,...) NAME
36+
#define cmdPrintln(...) CMDPRINTMACRO(__VA_ARGS__, cmdPrintln2, cmdPrintln1)(__VA_ARGS__)
37+
38+
#ifdef ECHO_DEBUG
39+
#define cmdPrint1(CMD) if(1) { \
40+
BC95Serial->print(CMD); \
41+
Serial.print(CMD); \
42+
}
43+
44+
#define cmdPrintln1(CMD) if(1) { \
45+
BC95Serial->println(CMD); \
46+
Serial.println(CMD); \
47+
}
48+
49+
#define cmdPrint2(CMD, ARG) if(1) { \
50+
BC95Serial->print(CMD,ARG); \
51+
Serial.print(CMD,ARG); \
52+
}
53+
54+
#define cmdPrintln2(CMD, ARG) if(1) { \
55+
BC95Serial->println(CMD,ARG); \
56+
Serial.println(CMD,ARG); \
57+
}
58+
#else
59+
#define cmdPrint1(CMD) BC95Serial->print(CMD);
60+
#define cmdPrintln1(CMD) BC95Serial->println(CMD);
61+
#define cmdPrint2(CMD, ARG) BC95Serial->print(CMD,ARG);
62+
#define cmdPrintln2(CMD, ARG) BC95Serial->println(CMD,ARG);
63+
#endif
64+
65+
typedef struct SOCKD SOCKD;
66+
struct SOCKD {
67+
uint8_t sockid;
68+
uint8_t status;
69+
uint16_t port;
70+
uint16_t msglen;
71+
uint16_t buff_msglen;
72+
uint16_t bc95_msglen;
73+
};
74+
75+
class BC95Class {
76+
public:
77+
BC95();
78+
79+
#if BC95_USE_EXTERNAL_BUFFER == 1
80+
void BC95Class::setExternalBuffer(char *sbuffer, size_t sbuffersize);
81+
#endif
82+
83+
SOCKD socketpool[MAXSOCKET];
84+
void begin(Stream &);
85+
char* getIMEI();
86+
char* getIMEI(char *);
87+
char* getIMSI();
88+
int8_t getSignalStrength();
89+
char* getManufacturerModel();
90+
char* getManufacturerRevision();
91+
92+
bool attachNetwork();
93+
char* getIPAddress();
94+
SOCKD* createSocket(uint16_t);
95+
void reset();
96+
int sendPacket(SOCKD* socket, IPAddress, uint16_t destPort, char *payload);
97+
int sendPacket(SOCKD* socket, IPAddress, uint16_t destPort, uint8_t *payload, size_t);
98+
char* fetchSocketPacket(SOCKD *socket, uint16_t len);
99+
void closeSocket(SOCKD *socket);
100+
101+
uint8_t* getBuffer();
102+
103+
private:
104+
Stream* BC95Serial;
105+
int readUntilDone(char* buff, uint32_t timeout, size_t);
106+
char* parseResponse(char* rawstr, char* pref);
107+
char* getSerialResponse(char *prefix);
108+
char* getSerialResponse(char *prefix, uint32_t timeout);
109+
};
110+
111+
#endif

0 commit comments

Comments
 (0)