-
Notifications
You must be signed in to change notification settings - Fork 733
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Trial to port Freematics SIM5360 to TinyGSM #189
Comments
I'll leave this open until I get to implementing this modem. Thank you! |
Hi, Thanks! |
Hi @vshymanskyy @8bit-bruno @laurentvm Did you ever get this to work? |
Got from issue comment in: vshymanskyy/TinyGSM#189
I added the code from above here, for easy review. |
@vshymanskyy Can you please have another look at this? I have several of these modules and can test whatever you like on a daily basis. |
I started skimming through the code above to see if I could smooth it in, but it has some odd customizations for the xb that it's written for and has some structural differences from how the others are written that make it difficult to proof. I'm not sure if it would even be faster to try and refactor it or to start with the SIM800 code and comb the manual for which AT commands changed. |
I started to port it, first based on the SIM800, then on SIM7000 (which seem meaningless as there are several types in the 7000 series). So I ended up taking bits and pieces from all three solutions trying to patch together something. (The 3 pieces being SIM5360 from above, SIM800 and SIM7000 header files.) At the end of the day I was trying to get the OTA over GSM working. Lot's of mods are needed, since all these devices are very different. Simply speaking, there are many AT command that doesn't have an equivalent in each. And the way this library is written, doesn't make things more transparent... I.e. @vshymanskyy why on earth are you writing all these complicated compiler definines, instead of putting stuff in *.cpp or header files? // Utility templates for writing/skipping characters on a stream
#define TINY_GSM_MODEM_STREAM_UTILITIES() \
template<typename T> \
void streamWrite(T last) { \
stream.print(last); \
} \
\
template<typename T, typename... Args> \
void streamWrite(T head, Args... tail) { \
stream.print(head); \
streamWrite(tail...); \
} \
\
template<typename... Args> \
void sendAT(Args... cmd) { \
streamWrite("AT", cmd..., GSM_NL); \
stream.flush(); \
TINY_GSM_YIELD(); \
/* DBG("### AT:", cmd...); */ \
} \
\
bool streamSkipUntil(const char c, const unsigned long timeout_ms = 1000L) { \
unsigned long startMillis = millis(); \
while (millis() - startMillis < timeout_ms) { \
while (millis() - startMillis < timeout_ms && !stream.available()) { \
TINY_GSM_YIELD(); \
} \
if (stream.read() == c) { \
return true; \
} \
} \
return false; \
}
This seem a like a promising project, but without more documentation it nearly impossible to contribute and improve. |
Sorry! Some of the complexity is from @vshymanskyy and a bunch is from me. Documentation is hard. All the complex defines are in the common file to avoid re-writing code while at the same time keeping the library small. The templates are for similar reasons. Using proper virtual classes would be (much) more readable and easier to maintain, but the size of the vtables is not zero and Tiny is an objective (See #280).
Buffer size - yup, tiny. You can use build flags to make it as big as you want. On the modules with on-board buffering, there's not really an advantage to a bigger buffer. The cellular chip's buffer is probably plenty big. On the modules without internal buffering (A6/ESP8266/Neoway M590, I think) you need to make your buffer big enough to capture the largest response you're expecting to get. The SIM800 and SIM7000 have the option of giving back characters from the buffer in HEX instead of ASCII. I'm not sure why you'd use it, but it's an option. |
Alright, here's something to try: https://github.com/EnviroDIY/TinyGSM No promises. It's created starting with the SIM7000 and just searching the AT manual to dump in commands where they seem to diverge. Test it with the examples and see if anything happens. |
@SRGDamia1 A few things/questions though:
|
I'm getting an immediate boot loop when using this with the FileDownload example. Any idea what could be causing this? |
1 - TINY_GSM_MUX_COUNT - The 5360 AT manual (v0.25, 16.20 AT+CIPOPEN) says there can be up to 10 simultaneous connections 2 - The TCP Rx buffer is 1500 bytes (see AT manual 16.35 AT+CIPRXGET). This library doesn't use any of the HTTP/HTTPS AT commands, it just opens the TCP client. I've honestly never tried to send/receive anything bigger. 3 - AT+CIPCLOSE is the command the manual gives for closing a socket in multi-socket mode. 4 - If you're getting spliced URC's, set the yield. ie, your debug log shows: 5 - Reboot sounds great. All I did was start with the 7000 and search the manual for the command. If the same command existed, I left it there. I didn't take the time to look if it was the best way of doing it. 6 - Fixed 7 - Fixed |
Before debugging the file download, how about posting some AT logs and getting the AllFunctions example working. |
@SRGDamia1 Awesome info there! The manual is so obscure and super easy to miss important details.
// Set GSM module baud rate
SerialAT.begin(115200);
delay(3000); Perhaps because I don't fully understand the comments here: // Set serial for debug console (to the Serial Monitor, default speed 115200)
#define SerialMon Serial
// Set serial for AT commands (to the module)
// Use Hardware Serial on Mega, Leonardo, Micro
#define SerialAT Serial1
// or Software Serial on Uno, Nano
//#include <SoftwareSerial.h>
//SoftwareSerial SerialAT(2, 3); // RX, TX
// Increase RX buffer to capture the entire response
// Chips without internal buffering (A6/A7, ESP8266, M590)
// need enough space in the buffer for the entire response
// else data will be lost (and the http library will fail).
#define TINY_GSM_RX_BUFFER 1024
// See all AT commands, if wanted
//#define DUMP_AT_COMMANDS
// Define the serial console for debug prints, if needed
#define TINY_GSM_DEBUG SerialMon
//#define LOGGING // <- Logging is for the HTTP library
I'll have a look at AllFunctions now, but I see you just pushed some changes to your other repo... |
I think that should be all the dependent libraries. Are you seeing any output at all when you're running the program? I think all of the examples have the serial baud set at 115200; make sure that's what your serial port monitor is set to.
HardwareSerial xbSerial(1);
#define SerialAT xbSerial Do uncomment |
Yeah, I'm trying to figure out where all your serial is going... // Set your reset, enable, power pins here
pinMode(20, OUTPUT);
digitalWrite(20, HIGH);
pinMode(23, OUTPUT);
digitalWrite(23, HIGH); Because on the Freematics there is no reset pin. So what you have up there is weird, and possibly dangerous, in case it is already connected to something else for output. in a different instance we have this: #define PIN_XBEE_PWR 27
SerialAT.begin(115200, SERIAL_8N1, 16, 17); // ESP: 16=UART#1 RX, 17=UART#1 TX |
Ok, I just tried the AllFunctions.ino with the following results:
change the relevant line to this: // EDIT HERE: Set your SIM PIN (within quotes) "nnnn", if any, otherwise leave as 0.
#define GSM_PIN 0
#define TINY_GSM_TEST_GPRS true
#define TINY_GSM_TEST_WIFI false
#define TINY_GSM_TEST_CALL false
#define TINY_GSM_TEST_SMS false
#define TINY_GSM_TEST_USSD false
#define TINY_GSM_TEST_BATTERY false
#define PIN_XBEE_PWR 27
bool sim_power_on() {
// The Freematics Esprit (SIM5360E) has a specific boot-up sequence
// that need to toggle power and wait for some setups.
Serial.printf("Waiting for PB DONE...\r\n");
pinMode(PIN_XBEE_PWR, OUTPUT);
digitalWrite(PIN_XBEE_PWR, HIGH);
delay(750);
digitalWrite(PIN_XBEE_PWR, LOW);
delay(2500);
//xbPurge(); // Discard any stale data <-- but depends: FreematicsPlus.h
digitalWrite(PIN_XBEE_PWR, HIGH);
delay(500);
digitalWrite(PIN_XBEE_PWR, LOW);
Serial.printf(".");
delay(10000); // Wait sufficiently long time for Modem to send last bootup message "PB DONE".
return true;
}
...
void setup() {
// Set console baud rate
SerialMon.begin(115200);
delay(100);
sim_power_on();
... |
The Bootup Sequence Look like this:
...and has to complete in order to ensure proper functionality. |
Alright, so copy that sim_power_on() function into your example and run it in place of the other pin mode changes. The examples are meant to be generic. You need to figure out the pins and stuff on your own. That's not the job of this library. |
By the way that turn on sequence is using the PWR_KEY on the SIM5620. |
Here is the current output log. |
To fix USSD, need to replace with this: #if TINY_GSM_TEST_USSD
String ussd_balance = modem.sendUSSD("*111#");
DBG("Balance (USSD):", ussd_balance);
String ussd_phone_num = modem.sendUSSD("*161#");
DBG("Phone number (USSD):", ussd_phone_num);
#endif
#endif |
It's not connecting to the network. It warns that NETOPEN isn't preferred but doesn't say what actually is. Let's try using the PDP commands. Update and try again. |
sendAT(GF("+CIPTIMEOUT="), 75000, ',', 15000, ',', 15000); |
I added the following to the header file, but it's still unhappy giving me an IP. // Define the PDP context
sendAT(GF("+CGDCONT=1,\"IP\",\""), apn, '"');
waitResponse();
// Activate the PDP profile/context 1
sendAT(GF("+CGACT=1,1")); // AT+CGACT=1
//waitResponse(60000L);
if (waitResponse(60000L) != 1) // was 150,000
return false;
// Attach to GPRS Packet domain)
sendAT(GF("+CGATT=1"));
if (waitResponse(60000L) != 1)
return false; |
Update from my fork and post the log please. Remember, I don't have any of the boards or chips you're working with. I can't help you if you're not posting the AT responses. |
I made some changes based on the TCP guide for the 7500/7600. Can you try both the AllFunctions and HttpClient examples and post the logs for both. |
Strangely enough, with only these 4 lines, I can get an IP after cold boot.
So I have no idea why we're trying to hop through all those hoops.
It's way after my social hour, so the above proposed testing have to wait until tomorrow. |
Typos fixed.
The AT log you posted had |
I'm not able to get the HttpClient to compile.
The lines in question are: TinyGsmClient client(modem);
HttpClient http(client, server, port); |
@SRGDamia1 The compile problem above, seem similar to #283... Any ideas? |
@eabase - as is mentioned in #238 and a few other issues, you can't use the most current ESP32 (1.0.2) core with the HttpClient library. That is a problem with the ESP32 core, not with TinyGSM.* Please complain on the issue over there: espressif/arduino-esp32#2755. Unfortunately, it doesn't look like it's going to be fixed for 1.0.3 either. I forgot about that issue when I suggested using the HttpClient example. Try the WebClient examples if you want to keep using the current ESP Core. |
bool isGprsConnected() {
sendAT(GF("+NETOPEN?"));
if (waitResponse(GF(GSM_NL "+NETOPEN:")) != 1) {
return false;
}
int res = stream.readStringUntil('\n').toInt();
waitResponse();
if (res != 1)
return false; But perhaps we should be doing something like this, instead? bool isGprsConnected() {
// The response should be: "+NETOPEN: 1,0" for an open/activated state
sendAT(GF("+NETOPEN?"));
//if (waitResponse(75000L, GF(GSM_NL "+NETOPEN: 1")) != 1) { // QQQ with a "," or not??
//if (waitResponse(75000L, GF(GSM_NL "+NETOPEN: 1,")) != 1) { // QQQ with a "," or not??
if (waitResponse(75000L, GF(GSM_NL "+NETOPEN: 1,0")) != 1) { // QQQ with a "," or not??
return false;
} and perhaps also wait even longer? Like ~120 s?
bool gprsDisconnect() {
// Before NETCLOSE we need to close all open sockets with:
// AT+CIPCLOSE Close TCP or UDP socket
// AT+CIPCLOSE=<link_num>
// ToDo: iterate?
sendAT(GF("+CIPCLOSE=1")); // Close <link_num> socket
if (waitResponse(60000L) != 1)
return false;
sendAT(GF("+NETCLOSE")); // Close the network (NOTE: ALL sockets should be closed first)
if (waitResponse(60000L) != 1)
return false; |
Could someone also explain the |
Manual says there will only be anything after the first 1 in the NETOPEN response if it isn't open, so just go as far as the 1. I suppose it doesn't hurt to close the sockets cleanly. |
|
Fixed |
WaitResponse is listening to the modem. If you give it a string to look for, it will continue to collect text from the modem until it gets to a string that ends with that text. If don't specify how long to search, it defaults to 1s. If you don't specify the text, it defaults to OK/ERROR. While it's listening for expected responses, it also keeps an ear out for URC (unsolicited response codes). If it gets a URC, it parses it appropriately - notifying a socket of new data or remoste closing, etc. |
I heavily reduced all the connection AT commands to only use the ones working from AT command line (as posted above), so now I finally got an IP! 🎉 It seem that the key was use a complete: According to AT Command manual, the responses to:
The AT sent is
|
PS. We're using |
We may need to fix the |
Garbage in the buffer shouldn't be a problem. waitResponse is only looking at the end of the string. |
But, if the chip says |
The CIPCLOSE should be ok with any of those responses. |
I'll have to wait until Monday to continue these tests. But FYI:
|
@SRGDamia1 As of today FileDownload.ino and a customized gsm only OTA, are both working using my updated and modified TinyGsmClientSIM5360.h code. I have made some readability improvements to the code formatting and also added a lot of comments. Some of the connect code that you added, but that seem not to be needed, has also been commented out. So feel free to add, augment and improve. Thanks again, and enjoy. 🥇
# From page 468 in AT command Manual
+CIPEVENT: NETWORK CLOSED UNEXPECTEDLY
Network is closed for network error(Out of service, etc). When this event happens,
user application needs to check and close all opened sockets, and then use AT+NETCLOSE
to release the network library if AT+NETOPEN? shows the network library is still opened.
+IPCLOSE: <client_index>, <close_reason>
Socket is closed passively.
<client_index>: a numeric parameter that identifies a connection.
The range of permitted values is 0 to 9.
<close_reason>: a numeric parameter that identifies the reason to close a client:
0– close connection forwardly
1– closed connection passively
2– reset connection because of timeout of sending data
+CLIENT: < link_num >,<server_index>,<client_IP>:<port>
TCP server accepted a new socket client,
the index is <link_num>,
the TCP server index is <server_index>.
The peer IP address is <client_IP>,
the peer port is <port>.
----------------------------------------
Unsolicited TCP/IP command <err> Codes
----------------------------------------
0 operation succeeded
1 Network failure
2 Network not opened
3 Wrong parameter
4 Operation not supported
5 Failed to create socket
6 Failed to bind socket
7 TCP server is already listening
8 Busy
9 Sockets opened
10 Timeout
11 DNS parse failed
255 Unknown error
---------------------------------------- and perhaps of less importance: ----------------------------------------
The ones relevant for Receiving Data (p.414):
----------------------------------------
+CIPRXGET:
// 1. If <mode> = 0 or 1: OK
// 2. If <mode> = 2 or 3:
// a. If single-client: +CIPRXGET: <mode>,<read_len>,<rest_len> <data>
// b. If multi-client: +CIPRXGET: <mode>,<cid>,<read_len>,<rest_len> <data>
// 3. If<mode> = 4:
// a. If single-client: +CIPRXGET: 4,<rest_len>
// b. If multi-client: +CIPRXGET: 4,<cid>,<rest_len>
// 4. If an error occurs: +IP ERROR: <error message>
+RECEIVE:
----------------------------------------
The ones relevant for Receiving HTTP (p.474):
----------------------------------------
+CHTTPS: RECV EVENT - When there is data cached in the receiving buffer
+CHTTPSNOTIFY: PEER CLOSED - The HTTPS session is closed by the server.
----------------------------------------
The ones relevant for Common Channel (p.474):
----------------------------------------
+CCHRECV: DATA, <session_id>,<len>
|
The |
Hi @SRGDamia1 and welcome back.
That can't be true, because we're certainly not running this as a server, and still get those URC's on regular basis. It's seem that the FW of that module must be doing other things then. Either way, it is still useful and important (for debugging purposes) to know what was the reason for closing any type of connections. |
Oops, sorry. |
I'm actually not sure now, since it's been 2 weeks since I was working on this. I was trying to download SW updates via web requests and also via FTP. I added the above comment because I occasionally got some weird closing behavior with those URC's. So I don't remember what exactly I was doing when these appeared. But certainly never running as a server of any kind. |
Would you please check all the functionality now and close this if it's working? |
@SRGDamia1 PS. I can't close someone else's issue. |
Hi Volodymyr ,
I tried to port your code to SIM5360 for freematics purpose:
https://github.com/stanleyhuangyc/Freematics/blob/master/ESPRIT/sim5360test/sim5360test.ino.
https://github.com/stanleyhuangyc/Freematics/blob/master/firmware_v5/traccar_client_sim5360/traccar_client_sim5360.ino
https://github.com/stanleyhuangyc/Freematics/blob/master/libraries/FreematicsPlus/FreematicsNetwork.cpp
As I'm not really not experienced with hardware, I did what I can up to now but I am stuck at the virtual read and write and available() function of the client.
If you want have some fun, you can review and try to complete the code attached below.
Laurent
The text was updated successfully, but these errors were encountered: