/* * Module_4g.c * * Created on: 2019-11-29 * Update on: 2020-11-26 * Author: Eason Yang * Version: V0.07 */ #include #include #include #include #include #include #include #include #include #include /*標準輸入輸出定義*/ #include /*標準函數庫定義*/ #include /*Unix 標準函數定義*/ #include /*檔控制定義*/ #include /*PPSIX 終端控制定義*/ #include /*錯誤號定義*/ #include #include #include #include #include "define.h" #define DEBUG_INFO(format, args...) StoreLogMsg("[%s:%d][%s][Info] "format, __FILE__, __LINE__, __FUNCTION__, ##args) #define DEBUG_WARN(format, args...) StoreLogMsg("[%s:%d][%s][Warn] "format, __FILE__, __LINE__, __FUNCTION__, ##args) #define DEBUG_ERROR(format, args...) StoreLogMsg("[%s:%d][%s][Error] "format, __FILE__, __LINE__, __FUNCTION__, ##args) #define ARRAY_SIZE(A) (sizeof(A) / sizeof(A[0])) #define PASS 1 #define FAIL -1 #define DONGLE_QUECTEL 1 #define DONGLE_UBLOX 2 // Define Module network mode #define NET_MODE_NO_SERVICE 0 #define NET_MODE_CDMA 1 #define NET_MODE_GMS_GPRS 2 #define NET_MODE_WCDMA 3 #define NET_MODE_GSM_WCDMA 4 #define NET_MODE_TD_SCDMA 5 #define NET_MODE_HSPA 6 #define NET_MODE_LTE 7 #define NET_MODE_UNKNOWN 9 // Define interval #define SystemInterval 30 // Seconds #define CheckModemInterval 30 // Seconds #define CheckSimInterval 30 // Seconds #define CheckModemInfoInterval 30 // Seconds #define CheckConnectionInterval 30 // Seconds #define CheckInternetInterval 30 // Seconds #define DisconnInterval 60 // Seconds // Define Telecom mode #define DISABLE_4G_MODULE 0 #define ENABLE_4G 1 int Check4GModem(void); int isPppUp(void); int isReadInfo(void); int isReadSimInfo(void); int isReachableInternet(void); int isModuleUnbind(void); int isModuleBind(void); int rstModule(void); int Load4gConfiguration(void); int CheckSignalRssi(void); int at_command(int uart, char* cmd, char* rx); int openPort(char *tty); int set_interface_attribs (int fd, int speed, int parity); int set_blocking (int fd, int should_block); void trim_s(char *s, unsigned char len); void substr(char *dest, const char* src, unsigned int start, unsigned int cnt); char *portName[3] = {"/dev/ttyUSB2", "/dev/ttyUSB2", "/dev/ttyACM2"}; char *valid_Internet[2] = {"8.8.8.8", "180.76.76.76"}; char *Version_And_Date[2] = {"V0.10","2021-03-16"}; pid_t pid; struct dongle_info { int Model; char ICCID[20]; char IMSI[16]; char IMEI[16]; char MANUFACTURER[8]; char MODELNAME[10]; char REVISION[18]; unsigned char MODE; int CSQ; int cnt_InternetFail; int cnt_ReadInfoFail; int cnt_pppFail; int cnt_SearchModuleFail; int cnt_ReadSimInfoFail; }Dongle; struct SysConfigAndInfo *ShmSysConfigAndInfo; struct StatusCodeData *ShmStatusCodeData; struct FanModuleData *ShmFanModuleData; struct OCPP16Data *ShmOCPP16Data; int StoreLogMsg(const char *fmt, ...) { char Buf[4096+256]; char buffer[4096]; time_t CurrentTime; struct tm *tm; va_list args; va_start(args, fmt); int rc = vsnprintf(buffer, sizeof(buffer), fmt, args); va_end(args); memset(Buf,0,sizeof(Buf)); CurrentTime = time(NULL); tm=localtime(&CurrentTime); sprintf(Buf,"echo -n \"[%04d.%02d.%02d %02d:%02d:%02d] - %s\" >> /Storage/SystemLog/[%04d.%02d]4g_SystemLog", tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec, buffer, tm->tm_year+1900,tm->tm_mon+1); #ifdef SystemLogMessage system(Buf); #endif #ifdef ConsloePrintLog printf("[%04d.%02d.%02d %02d:%02d:%02d] - %s", tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec, buffer); #endif return rc; } int DiffTimeb(struct timeb ST, struct timeb ET) { //return milli-second unsigned int StartTime,StopTime; StartTime=(unsigned int)ST.time; StopTime=(unsigned int)ET.time; return (StopTime-StartTime)*1000+ET.millitm-ST.millitm; } //========================================== // Init all share memory //========================================== int InitShareMemory() { int result = PASS; int MeterSMId; //creat ShmSysConfigAndInfo if ((MeterSMId = shmget(ShmSysConfigAndInfoKey, sizeof(struct SysConfigAndInfo), 0777)) < 0) { DEBUG_ERROR("shmget ShmSysConfigAndInfo NG\n"); result = FAIL; } else if ((ShmSysConfigAndInfo = shmat(MeterSMId, NULL, 0)) == (void *) -1) { DEBUG_ERROR("shmat ShmSysConfigAndInfo NG\n"); result = FAIL; } else {} //creat ShmStatusCodeData if ((MeterSMId = shmget(ShmStatusCodeKey, sizeof(struct StatusCodeData), 0777)) < 0) { DEBUG_ERROR("shmget ShmStatusCodeData NG\n"); result = FAIL; } else if ((ShmStatusCodeData = shmat(MeterSMId, NULL, 0)) == (void *) -1) { DEBUG_ERROR("shmat ShmStatusCodeData NG\n"); result = FAIL; } else {} //creat ShmOCPP16Data if ((MeterSMId = shmget(ShmOcppModuleKey, sizeof(struct OCPP16Data), 0777)) < 0) { DEBUG_ERROR("shmget ShmOCPP16Data NG"); result = FAIL; } else if ((ShmOCPP16Data = shmat(MeterSMId, NULL, 0)) == (void *) -1) { DEBUG_ERROR("shmat ShmOCPP16Data NG"); result = FAIL; } else {} return result; } //========================================== // Check dongle model //========================================== int Check4GModem(void) { int result = FAIL; if((access("/dev/ttyUSB0", F_OK) != -1) && (access("/dev/ttyUSB1", F_OK) != -1) && (access("/dev/ttyUSB2", F_OK) != -1) && (access("/dev/ttyUSB3", F_OK) != -1)) { result = DONGLE_QUECTEL; } else if((access("/dev/ttyACM0", F_OK) != -1) && (access("/dev/ttyACM1", F_OK) != -1) && (access("/dev/ttyACM2", F_OK) != -1) && (access("/dev/ttyACM3", F_OK) != -1)) { result = DONGLE_UBLOX; } else {} if(result == DONGLE_QUECTEL) { DEBUG_INFO("Quectel 4G modem be found\n"); } else if(result == DONGLE_UBLOX) { DEBUG_INFO("Ublox 4G modem be found\n"); } else { DEBUG_WARN("No 4G modem be found\n"); } return result; } //========================================== // Check ppp interface status //========================================== int isPppUp(void) { int result = FAIL; FILE *fp; char cmd[256]; char buf[512]; char tmp[512]; strcpy(cmd, "ifconfig ppp0");; fp = popen(cmd, "r"); if(fp != NULL) { while(fgets(buf, sizeof(buf), fp) != NULL) { if(strstr(buf, "ppp") > 0) { result = PASS; } if(strstr(buf, "addr:") > 0) { sscanf(buf, "%*s%s", tmp); substr((char*)ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomIpAddress, tmp, strspn(tmp, "addr:"), (strlen(tmp) - strspn(tmp, "addr:"))); } } } pclose(fp); return result; } //========================================== // Check dongle info read status //========================================== int isReadInfo(void) { int result = PASS; int uart; char rx[512]; char tmp[512]; char Length; if((uart = openPort(portName[Dongle.Model])) != FAIL) { switch(Dongle.Model) { case DONGLE_QUECTEL: default: //============================== // Set don't echo command //============================== Length = at_command(uart, "ate0\r", rx); if(Length > 0) { if(strstr(rx, "ERROR")) { result = FAIL; } else {} } else result = FAIL; //============================== // Read Manufacturer //============================== Length = at_command(uart, "at+gmi\r", rx); if(Length > 0) { memset(tmp, 0, sizeof tmp); memcpy(tmp, rx, strcspn(rx,"OK")); memset(rx, 0, sizeof rx); trim_s(tmp,Length); if(strstr(tmp, "atgmi") != NULL) { substr(tmp, tmp, 5, strlen(tmp)-5); } memset(Dongle.MANUFACTURER, 0x00, ARRAY_SIZE(Dongle.MANUFACTURER)); strncpy(Dongle.MANUFACTURER, tmp, strlen(tmp)); } else result = FAIL; //============================== // Read Model //============================== Length = at_command(uart, "at+gmm\r", rx); if(Length > 0) { memset(tmp, 0, sizeof tmp); memcpy(tmp, rx, strcspn(rx,"OK")); memset(rx, 0, sizeof rx); trim_s(tmp,Length); if(strstr(tmp, "atgmm") != NULL) { substr(tmp, tmp, 5, strlen(tmp)-5); } memset(Dongle.MODELNAME, 0x00, ARRAY_SIZE(Dongle.MODELNAME)); strncpy(Dongle.MODELNAME, tmp, strlen(tmp)); } else result = FAIL; //============================== // Read Revision //============================== Length = at_command(uart, "at+gmr\r", rx); if(Length > 0) { memset(tmp, 0, sizeof tmp); memcpy(tmp, rx, strcspn(rx, "OK")); memset(rx, 0, sizeof rx); trim_s(tmp,Length); if(strstr(tmp, "atgmr") != NULL) { substr(tmp, tmp, 5, strlen(tmp)-5); } memset(Dongle.REVISION, 0x00, ARRAY_SIZE(Dongle.REVISION)); strncpy(Dongle.REVISION, tmp, strlen(tmp)); } else result = FAIL; //============================== // Read IMEI //============================== Length = at_command(uart, "at+gsn\r", rx); if(Length > 0) { memset(tmp, 0, sizeof tmp); memcpy(tmp, rx, strcspn(rx, "OK")); memset(rx, 0, sizeof rx); trim_s(tmp,Length); if(strstr(tmp, "atgsn") != NULL) { substr(tmp, tmp, 5, strlen(tmp)-5); } memset(Dongle.IMEI, 0x00, ARRAY_SIZE(Dongle.IMEI)); strncpy(Dongle.IMEI, tmp, strlen(tmp)); } else result = FAIL; //============================== // Read CSQ //============================== Length = at_command(uart, "at+csq\r", rx); if(Length > 0) { memset(tmp, 0, sizeof tmp); memcpy(tmp, rx, strcspn(rx,",")); strncpy(rx, tmp + strcspn(tmp,":")+1, 10); Dongle.CSQ = atoi(rx); } else result = FAIL; //============================== // Read Mode //============================== Length = at_command(uart, "at+qnwinfo\r", rx); if(Length > 0) { memset(tmp, 0, sizeof tmp); strncpy(tmp, &rx[strcspn(rx,":")+2], strcspn(rx,",")-(strcspn(rx,":")+2)); if(strstr(tmp, "CDMA") != NULL) Dongle.MODE = NET_MODE_CDMA; else if((strstr(tmp, "GPRS") != NULL) || (strstr(tmp, "EDGE") != NULL)) Dongle.MODE = NET_MODE_GMS_GPRS; else if(strstr(tmp, "WCDMA") != NULL) Dongle.MODE = NET_MODE_WCDMA; else if(strstr(tmp, "GSM") != NULL) Dongle.MODE = NET_MODE_GSM_WCDMA; else if(strstr(tmp, "TDSCDMA") != NULL) Dongle.MODE = NET_MODE_TD_SCDMA; else if(strstr(tmp, "LTE") != NULL) Dongle.MODE = NET_MODE_LTE; else if((strstr(tmp, "HSDPA") != NULL) || (strstr(tmp, "HSUPA") != NULL) || (strstr(tmp, "HSPA+") != NULL)) Dongle.MODE = NET_MODE_HSPA; else Dongle.MODE = NET_MODE_UNKNOWN; } else result = FAIL; break; case DONGLE_UBLOX: //============================== // Set don't echo command //============================== Length = at_command(uart, "ate0\r", rx); if(Length > 0) { if(strstr(rx, "ERROR")) { result = FAIL; } else {} } else result = FAIL; //============================== // Read Manufacturer //============================== Length = at_command(uart, "at+cgmi\r", rx); if(Length > 0) { memset(tmp, 0, sizeof tmp); memcpy(tmp, rx, strcspn(rx,"OK")); memset(rx, 0, sizeof rx); memset(Dongle.MANUFACTURER, 0x00, ARRAY_SIZE(Dongle.MANUFACTURER)); strncpy(Dongle.MANUFACTURER, tmp+2, 6); } else result = FAIL; //============================== // Read Model //============================== Length = at_command(uart, "at+cgmm\r", rx); if(Length > 0) { memset(tmp, 0, sizeof tmp); memcpy(tmp, rx, strcspn(rx,"OK")); memset(rx, 0, sizeof rx); memset(Dongle.MODELNAME, 0x00, ARRAY_SIZE(Dongle.MODELNAME)); strncpy(Dongle.MODELNAME , tmp+2, 9); } else result = FAIL; //============================== // Read Revision //============================== Length = at_command(uart, "at+cgmr\r", rx); if(Length > 0) { memset(tmp, 0, sizeof tmp); memcpy(tmp, rx, strcspn(rx, "OK")); memset(rx, 0, sizeof rx); memset(Dongle.REVISION, 0x00, ARRAY_SIZE(Dongle.REVISION)); strncpy(Dongle.REVISION, tmp+2, 5); } else result = FAIL; //============================== // Read IMEI //============================== Length = at_command(uart, "at+cgsn\r", rx); if(Length > 0) { memset(tmp, 0, sizeof tmp); memcpy(tmp, rx, strcspn(rx, "OK")); memset(rx, 0, sizeof rx); trim_s(tmp,Length); memset(Dongle.IMEI, 0x00, ARRAY_SIZE(Dongle.IMEI)); strncpy(Dongle.IMEI, tmp, strlen(tmp)); } else result = FAIL; //============================== // Read CSQ //============================== Length = at_command(uart, "at+csq\r", rx); if(Length > 0) { memset(tmp, 0, sizeof tmp); memcpy(tmp, rx, strcspn(rx,",")); strncpy(rx, tmp + strcspn(tmp,":")+1, 10); Dongle.CSQ = atoi(rx); } else result = FAIL; break; } } else { #ifdef SystemLogMessage DEBUG_ERROR("%s open fail.\n", portName[Dongle.Model]); #endif result = FAIL; } close(uart); return result; } //========================================== // Read sim card information //========================================== int isReadSimInfo(void) { int result = PASS; int uart; char rx[512]; char tmp[512]; char Length; if((uart = openPort(portName[Dongle.Model])) != FAIL) { switch(Dongle.Model) { case DONGLE_QUECTEL: default: //============================== // Set don't echo command //============================== Length = at_command(uart, "ate0\r", rx); if(Length > 0) { if(strstr(rx, "ERROR")) { result = FAIL; } else {} } else result = FAIL; //============================== // Read IMSI //============================== Length = at_command(uart, "at+cimi\r", rx); if(Length > 0) { memset(tmp, 0, sizeof tmp); if(strstr(rx, "ERROR")) { memset(Dongle.IMSI, 0, sizeof Dongle.IMSI); result = FAIL; } else { memcpy(tmp, rx, strcspn(rx, "OK")); trim_s(tmp, Length); memset(rx, 0, sizeof rx); if(strstr(tmp, "atcimi") != NULL) { substr(tmp, tmp, 6, strlen(tmp)-6); } memset(Dongle.IMSI, 0x00, ARRAY_SIZE(Dongle.IMSI)); strncpy(Dongle.IMSI, tmp, strlen(tmp)); } } else result = FAIL; //============================== // Read CCID //============================== Length = at_command(uart, "at+qccid\r", rx); if(Length > 0) { memset(tmp, 0, sizeof tmp); if(strstr(rx, "ERROR")) { memset(Dongle.ICCID, 0, sizeof Dongle.ICCID); result = FAIL; } else { memcpy(tmp, rx, strcspn(rx, "OK")); memset(rx, 0, sizeof rx); memset(Dongle.ICCID, 0x00, ARRAY_SIZE(Dongle.ICCID)); strncpy(Dongle.ICCID, tmp + strcspn(tmp, ":") + 2, 20); } } else result = FAIL; break; case DONGLE_UBLOX: //============================== // Set don't echo command //============================== Length = at_command(uart, "ate0\r", rx); if(Length > 0) { if(strstr(rx, "ERROR")) { result = FAIL; } else {} } else result = FAIL; //============================== // Read IMSI //============================== Length = at_command(uart, "at+cimi\r", rx); if(Length > 0) { memset(tmp, 0, sizeof tmp); if(strstr(rx, "ERROR")) { memset(Dongle.IMSI, 0, sizeof Dongle.IMSI); result = FAIL; } else { memcpy(tmp, rx, strcspn(rx,"OK")); memset(rx, 0, sizeof rx); trim_s(tmp,Length); if(strstr(tmp, "atcimi") != NULL) { substr(tmp, tmp, 6, strlen(tmp)-6); } memset(Dongle.IMSI, 0x00, ARRAY_SIZE(Dongle.IMSI)); strncpy(Dongle.IMSI, tmp, strlen(tmp)); } } else result = FAIL; //============================== // Read CCID //============================== Length = at_command(uart, "at+ccid\r", rx); if(Length > 0) { memset(tmp, 0, sizeof tmp); if(strstr(rx, "ERROR")) { memset(Dongle.ICCID, 0, sizeof Dongle.ICCID); result = FAIL; } else { memcpy(tmp, rx, strcspn(rx, "OK")); memset(rx, 0, sizeof rx); memset(Dongle.ICCID, 0x00, ARRAY_SIZE(Dongle.ICCID)); strncpy(Dongle.ICCID, tmp + strcspn(tmp, ":") + 2, 20); } } else result = FAIL; break; } } else { DEBUG_ERROR("%s open fail.\n", portName[Dongle.Model]); result = FAIL; } close(uart); return result; } //========================================== // Read signal information //========================================== int CheckSignalRssi(void) { int result = PASS; int uart; char rx[512]; char tmp[512]; char Lenght; if((uart = openPort(portName[Dongle.Model])) != FAIL) { switch (Dongle.Model) { case DONGLE_UBLOX: //============================== // Set don't echo command //============================== Lenght = at_command(uart, "ate0\r", rx); if(Lenght > 0) { if(strstr(rx, "ERROR")) { result = FAIL; } else {} } else result = FAIL; //============================== // Read CSQ //============================== Lenght = at_command(uart, "at+csq\r", rx); if(Lenght > 0) { memset(tmp, 0, sizeof tmp); memcpy(tmp, rx, strcspn(rx, ",")); strncpy(rx, tmp + strcspn(tmp, ":") + 1, 10); Dongle.CSQ = atoi(rx); } else result = FAIL; break; case DONGLE_QUECTEL: default: //============================== // Set don't echo command //============================== Lenght = at_command(uart, "ate0\r", rx); if(Lenght > 0) { if(strstr(rx, "ERROR")) { result = FAIL; } else {} } else result = FAIL; //============================== // Read CSQ //============================== Lenght = at_command(uart, "at+csq\r", rx); if(Lenght > 0) { memset(tmp, 0, sizeof tmp); memcpy(tmp, rx, strcspn(rx, ",")); strncpy(rx, tmp + strcspn(tmp, ":") + 1, 10); Dongle.CSQ = atoi(rx); } else result = FAIL; break; } } else { #ifdef SystemLogMessage DEBUG_ERROR("%s open fail.\n", portName[Dongle.Model]); #endif result = FAIL; } close(uart); return result; } //========================================== // Init 4G dongle configuration //========================================== int Load4gConfiguration() { int result = FAIL; unsigned char CopyTmp[1024]; if(strlen((char*)ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomApn) > 0) { system("cat /dev/null > /root/ppp/auto-apn.conf"); system("chmod 600 /root/ppp/auto-apn.conf"); system("cat /dev/null > /etc/ppp/pap-secrets"); system("chmod 600 /etc/ppp/pap-secrets"); system("cat /dev/null > /etc/ppp/chap-secrets"); system("chmod 600 /etc/ppp/chap-secrets"); system("cat /dev/null > /etc/ppp/auth"); system("chmod 600 /etc/ppp/auth"); memset(CopyTmp,0,sizeof(CopyTmp)); sprintf((char*)CopyTmp,"echo APN=\"%s\" > /root/ppp/auto-apn.conf",ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomApn); system((char*)CopyTmp); memset(CopyTmp,0,sizeof(CopyTmp)); sprintf((char*)CopyTmp,"echo ACCOUNT=\"%s\" >> /root/ppp/auto-apn.conf",ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomChapPapId); system((char*)CopyTmp); memset(CopyTmp,0,sizeof(CopyTmp)); sprintf((char*)CopyTmp,"echo PASSWORD=\"%s\" >> /root/ppp/auto-apn.conf",ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomChapPapPwd); system((char*)CopyTmp); memset(CopyTmp,0,sizeof(CopyTmp)); sprintf((char*)CopyTmp,"echo %s > /etc/ppp/auth",ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomChapPapId); system((char*)CopyTmp); sprintf((char*)CopyTmp,"echo %s >> /etc/ppp/auth",ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomChapPapPwd); system((char*)CopyTmp); if(strlen((char*)ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomChapPapId)>0) { memset(CopyTmp,0,sizeof(CopyTmp)); if(strlen((char*)ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomChapPapPwd)>0) sprintf((char*)CopyTmp,"echo \"%s * %s \" > /etc/ppp/pap-secrets", ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomChapPapId, ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomChapPapPwd); else sprintf((char*)CopyTmp,"echo \"%s * \\ \" > /etc/ppp/pap-secrets", ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomChapPapId); system((char*)CopyTmp); memset(CopyTmp,0,sizeof(CopyTmp)); if(strlen((char*)ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomChapPapPwd)>0) sprintf((char*)CopyTmp,"echo \"%s * %s \" > /etc/ppp/chap-secrets", ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomChapPapId, ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomChapPapPwd); else sprintf((char*)CopyTmp,"echo \"%s * \\ \" > /etc/ppp/chap-secrets", ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomChapPapId); system((char*)CopyTmp); } result = PASS; } return result; } //========================================== // Check internet access status //========================================== int isReachableInternet(void) { int result = FAIL; FILE *fp; char cmd[256]; char buf[512]; char tmp[256]; char isPppGetGw = FALSE; for(int idx=0;idx 0) { //sscanf(buf, "%*s%*s%*s%*s%*s%s", tmp); if(strstr(buf,"100%") != NULL) {} else { result = PASS; } //DEBUG_INFO("%s",buf); //DEBUG_INFO("%s\n",tmp); } } } pclose(fp); } // Check ppp0 gateway if(result == TRUE) { fp = popen("ip route", "r"); if(fp == NULL) result = FAIL; else { while(fgets(buf, sizeof(buf), fp) != NULL) { if((strstr(buf, "default") != NULL) && (strstr(buf, "ppp0") != NULL)) { isPppGetGw = TRUE; break; } if(strstr(buf, "ppp0") != NULL) { break; } } if((isPppGetGw == FALSE) && (strstr(buf, "ppp0") != NULL)) { sscanf(buf, "%s", tmp); DEBUG_INFO("ppp0 does not get default route gateway force assign to %s\n", tmp); sprintf(cmd,"route add default gw %s ppp0 &", tmp); system(cmd); } } pclose(fp); memset(buf, 0x00, sizeof(buf)); } return result; } //========================================== // Unbind USB port //========================================== int isModuleUnbind(void) { int result = FAIL; FILE *fp; char cmd[256]; strcpy(cmd, "echo '1-1'> /sys/bus/usb/drivers/usb/unbind"); fp = popen(cmd, "r"); if(fp == NULL) { result = FAIL; } else { result = PASS; #ifdef SystemLogMessage DEBUG_INFO("Unbind USB for dongle.\n"); #endif } return result; } //========================================== // Bind USB port //========================================== int isModuleBind(void) { int result = FAIL; FILE *fp; char cmd[256]; strcpy(cmd, "echo '1-1'> /sys/bus/usb/drivers/usb/bind"); fp = popen(cmd, "r"); if(fp == NULL) { result = FAIL; } else { #ifdef SystemLogMessage DEBUG_INFO("Bind USB for dongle.\n"); #endif result = PASS; } return result; } //========================================== // Dongle reset process //========================================== int rstModule(void) { int result = PASS; int uart; char rx[512]; if((uart = openPort(portName[Dongle.Model])) != FAIL) { //============================== // Reset module //============================== switch(Dongle.Model) { case DONGLE_QUECTEL: default: if(at_command(uart, "at+cfun=1,1\r", rx) <= 0) { result = FAIL; } DEBUG_INFO("Dongle hardware reset...\n"); break; case DONGLE_UBLOX: if(at_command(uart, "at+cfun=1,1\r", rx) <= 0) { result = FAIL; } DEBUG_INFO("Dongle hardware reset...\n"); break; } } else { #ifdef SystemLogMessage DEBUG_ERROR("%s open fail.\n", portName[Dongle.Model]); #endif result = FAIL; } close(uart); sleep(40); return result; } //========================================== // AT command send/receive //========================================== int at_command(int uart, char* cmd, char* rx) { int len; //sleep(2); //required to make flush work, for some reason //DEBUG_INFO("cmd : %s \n", cmd); tcflush(uart,TCIOFLUSH); if(write(uart, cmd, strlen(cmd)) >= sizeof(cmd)) { usleep(500000); len = read(uart, rx, 512); //DEBUG_INFO("rx : %s \n", rx); } else { #ifdef SystemLogMessage DEBUG_ERROR("AT command %s response fail.\n", cmd); #endif } return len; } //========================================== // Dongle communication port open //========================================== int openPort(char *tty) { int uart = open(tty, O_RDWR | O_NOCTTY | O_NDELAY); if(uart!=FAIL) { if((set_interface_attribs(uart, B115200, 0) != PASS) || (set_blocking(uart, 0) != PASS)) uart = FAIL; } return uart; } //========================================== // Port parameter set //========================================== int set_interface_attribs (int fd, int speed, int parity) { int result = FAIL; struct termios tty; memset (&tty, 0, sizeof tty); if (tcgetattr (fd, &tty) == 0) { cfsetospeed (&tty, speed); cfsetispeed (&tty, speed); tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars // disable IGNBRK for mismatched speed tests; otherwise receive break // as \000 chars tty.c_iflag &= ~IGNBRK; // disable break processing tty.c_lflag = 0; // no signaling chars, no echo, // no canonical processing tty.c_oflag = 0; // no remapping, no delays tty.c_cc[VMIN] = 0; // read doesn't block tty.c_cc[VTIME] = 10; // 1 seconds read timeout tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl tty.c_cflag |= (CLOCAL | CREAD); // ignore modem controls, // enable reading tty.c_cflag &= ~(PARENB | PARODD); // shut off parity tty.c_cflag |= parity; tty.c_cflag &= ~CSTOPB; tty.c_cflag &= ~CRTSCTS; if (tcsetattr (fd, TCSANOW, &tty) == 0) result = PASS; } return result; } int set_blocking (int fd, int should_block) { int result = FAIL; struct termios tty; memset (&tty, 0, sizeof tty); if (tcgetattr (fd, &tty) == 0) { tty.c_cc[VMIN] = should_block ? 1 : 0; tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout if (tcsetattr (fd, TCSANOW, &tty) == 0) result = PASS; } return result; } //========================================== // Common routine //========================================== void trim_s(char *s, unsigned char len) { for(unsigned char i = 0 ; i < len; i++) { if (!((s[i]>='a') && (s[i]<='z')) && !((s[i]>='A') && (s[i]<='Z'))&& !((s[i]>='0') && (s[i]<='9'))) { s[i] = s[i + 1]; strncpy(s + i, s + i + 1, len); i -= 1; len -= 1; } } s[len + 1] = '\0'; } void substr(char *dest, const char* src, unsigned int start, unsigned int cnt) { strncpy(dest, src + start, cnt); dest[cnt] = 0; } int csq2rssi(int csq) { int result = 0; switch(csq) { case 0 ... 31: result = -113+(2*csq); break; case 100 ... 191: result = -116 + (csq-102); break; case 99: case 199: default: result = csq; break; } return result; } //========================================== // Main process //========================================== int main(void) { //========================================== //Initialization share memory //========================================== if(InitShareMemory() == FAIL) { #ifdef SystemLogMessage DEBUG_ERROR("InitShareMemory NG\n"); #endif if(ShmStatusCodeData!=NULL) { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.FailToCreateShareMemory=1; } sleep(5); return 0; } DEBUG_INFO("========================================\n"); DEBUG_INFO("Latest Firmware Version : [ %s ].\n", Version_And_Date[0]); DEBUG_INFO("Latest Upgrade Date : [ %s ].\n", Version_And_Date[1]); DEBUG_INFO("========================================\n"); for(;;) { TOP: switch(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomEnabled) { case ENABLE_4G: DEBUG_INFO("4G module : [ Enable ].\n"); if(((Dongle.Model = Check4GModem()) != FAIL)) { ShmStatusCodeData->FaultCode.FaultEvents.bits.Telecom4GModuleBroken = 0; Dongle.cnt_SearchModuleFail = 0; if(isReadInfo() == PASS) { if(strcmp((char*)ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModelName, Dongle.MODELNAME) != 0) memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModelName, 0x00, ARRAY_SIZE(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModelName)); memcpy(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModelName, Dongle.MODELNAME, sizeof Dongle.MODELNAME); if(strcmp((char*)ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSoftwareVer, Dongle.REVISION) != 0) memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSoftwareVer, 0x00, ARRAY_SIZE(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSoftwareVer)); memcpy(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSoftwareVer, Dongle.REVISION, sizeof Dongle.REVISION); if(strcmp((char*)ShmSysConfigAndInfo->SysInfo.TelcomModemFwRev, Dongle.REVISION) != 0) memset(ShmSysConfigAndInfo->SysInfo.TelcomModemFwRev, 0x00, ARRAY_SIZE(ShmSysConfigAndInfo->SysInfo.TelcomModemFwRev)); memcpy(ShmSysConfigAndInfo->SysInfo.TelcomModemFwRev, Dongle.REVISION, sizeof Dongle.REVISION); if(strcmp((char*)ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModemImei, Dongle.IMEI) != 0) memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModemImei, 0x00, ARRAY_SIZE(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModemImei)); memcpy(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModemImei, Dongle.IMEI, sizeof Dongle.IMEI); ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomRssi = csq2rssi(Dongle.CSQ); ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModemMode = Dongle.MODE; DEBUG_INFO("========================================\n"); DEBUG_INFO("Status: Device info readable...\n"); DEBUG_INFO("========================================\n"); DEBUG_INFO("Device MANUFACTURER: %s\n", Dongle.MANUFACTURER); DEBUG_INFO("Device MODEL: %s\n", ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModelName); DEBUG_INFO("Device REVISION: %s\n", ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSoftwareVer); DEBUG_INFO("Device IMEI: %s\n", ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModemImei); DEBUG_INFO("Device RSSI: %d dBm (CSQ:%d)\n", ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomRssi, Dongle.CSQ); DEBUG_INFO("Device MODE: %d\n", ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModemMode); DEBUG_INFO("========================================\n"); Dongle.cnt_ReadInfoFail = 0; if(isReadSimInfo() == PASS) { ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimStatus = 1; if(strcmp((char*)ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimIccid, Dongle.ICCID) != 0) memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimIccid, 0x00, ARRAY_SIZE(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimIccid)); memcpy(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimIccid, Dongle.ICCID, sizeof Dongle.ICCID); if(strcmp((char*)ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimImsi, Dongle.IMSI) != 0) memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimImsi, 0x00, ARRAY_SIZE(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimImsi)); memcpy(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimImsi, Dongle.IMSI, sizeof Dongle.IMSI); DEBUG_INFO("========================================\n"); DEBUG_INFO("Status: SIM card info readable...\n"); DEBUG_INFO("========================================\n"); DEBUG_INFO("Device IMSI: %s\n", ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimImsi); DEBUG_INFO("Device ICCID: %.20s\n", ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimIccid); DEBUG_INFO("TelcomSimStatus: %d\n", ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimStatus); DEBUG_INFO("========================================\n"); Dongle.cnt_ReadSimInfoFail = 0; if(isPppUp() == PASS) { DEBUG_INFO("========================================\n"); DEBUG_INFO("Status: PPP interface found...\n"); DEBUG_INFO("========================================\n"); DEBUG_INFO("PPP IP: %s\n", ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomIpAddress); DEBUG_INFO("========================================\n"); Dongle.cnt_pppFail = 0; if(isReachableInternet() == PASS) { ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomNetworkConn = 1; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.Telecom4GModuleCommFail = 0; ShmStatusCodeData->InfoCode.InfoEvents.bits.InternetDisconnectVia4Gi = 0; ShmStatusCodeData->InfoCode.InfoEvents.bits.ApnDisconnectVia4Gi = 0; Dongle.cnt_InternetFail = 0; // Update Rssi Value if(CheckSignalRssi() != PASS) DEBUG_INFO("No RSSI\n"); else ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomRssi = csq2rssi(Dongle.CSQ); DEBUG_INFO("========================================\n"); DEBUG_INFO("Status: 4G Device connecting...\n"); DEBUG_INFO("========================================\n"); DEBUG_INFO("Network connection: %d\n", ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomNetworkConn); DEBUG_INFO("Dongle internet valid result: Pass\n"); DEBUG_INFO("========================================\n"); // Escape to the top if(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomEnabled == DISABLE_4G_MODULE) { goto TOP; } sleep(CheckInternetInterval); } else { DEBUG_INFO("Dongle internet valid result: Fail %d time\n", Dongle.cnt_InternetFail); ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomNetworkConn = 0; ShmStatusCodeData->InfoCode.InfoEvents.bits.InternetDisconnectVia4Gi = 1; ShmStatusCodeData->InfoCode.InfoEvents.bits.ApnDisconnectVia4Gi = 1; Dongle.cnt_InternetFail++; if(Dongle.cnt_InternetFail > 3) { system("killall 4GDetection"); system("killall pppd"); sleep(2); Dongle.cnt_InternetFail = 0; rstModule(); } sleep(DisconnInterval); } } else { if(Load4gConfiguration() == FAIL) { DEBUG_ERROR("4G configuration value NG.\n"); if(ShmStatusCodeData!=NULL) { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.Telecom4GModuleCommFail=1; } } else { DEBUG_WARN("PPP interface not found.\n"); memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomIpAddress, 0 , sizeof ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomIpAddress); Dongle.cnt_pppFail++; if(Dongle.cnt_pppFail > 3) { system("killall 4GDetection"); system("killall pppd"); sleep(2); Dongle.cnt_pppFail = 0; rstModule(); } system("killall 4GDetection"); system("killall pppd"); sleep(2); if(Dongle.Model == DONGLE_QUECTEL) { system("/root/ppp/4GDetection /dev/ttyUSB3 &"); printf("4GDetection for primary device.\n"); } else if(Dongle.Model == DONGLE_UBLOX) { system("/root/ppp/4GDetection /dev/ttyACM0 &"); printf("4GDetection for second device.\n"); } else {} } sleep(CheckConnectionInterval); } } else { DEBUG_ERROR("SIM card info read error fail: %d\n", Dongle.cnt_ReadSimInfoFail); ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimStatus = 0; memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimImsi, 0, sizeof ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimImsi); memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimIccid, 0, sizeof ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimIccid); memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomIpAddress, 0 , sizeof ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomIpAddress); DEBUG_INFO("========================================\n"); DEBUG_INFO("Status: Read Sim card info fail...\n"); DEBUG_INFO("Device ICCID: %.20s\n", ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimIccid); DEBUG_INFO("Device IMSI: %s\n", ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimImsi); DEBUG_INFO("========================================\n"); Dongle.cnt_ReadSimInfoFail ++; if(Dongle.cnt_ReadSimInfoFail > 3) { system("killall 4GDetection"); system("killall pppd"); sleep(2); Dongle.cnt_ReadSimInfoFail = 0; rstModule(); } sleep(CheckSimInterval); } } else { DEBUG_ERROR("Device info read error fail: %d\n", Dongle.cnt_ReadInfoFail); Dongle.MODE = NET_MODE_NO_SERVICE; memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModelName, 0, sizeof ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModelName); memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSoftwareVer, 0, sizeof ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSoftwareVer); memset(ShmSysConfigAndInfo->SysInfo.TelcomModemFwRev, 0, sizeof ShmSysConfigAndInfo->SysInfo.TelcomModemFwRev); memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModemImei, 0, sizeof ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModemImei); ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomRssi = 0; ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModemMode = 0; DEBUG_INFO("========================================\n"); DEBUG_INFO("Status: Read device info fail...\n"); DEBUG_INFO("Device MANUFACTURER: %s\n", Dongle.MANUFACTURER); DEBUG_INFO("Device MODEL: %s\n", ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModelName); DEBUG_INFO("Device REVISION: %s\n", ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSoftwareVer); DEBUG_INFO("Device IMEI: %s\n", ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModemImei); DEBUG_INFO("Device RSSI: %d dBm (CSQ:%d)\n", ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomRssi, Dongle.CSQ); DEBUG_INFO("Device MODE: %d\n", ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModemMode); DEBUG_INFO("========================================\n"); Dongle.cnt_ReadInfoFail++; if(Dongle.cnt_ReadInfoFail > 3) { system("killall 4GDetection"); system("killall pppd"); sleep(2); Dongle.cnt_ReadInfoFail = 0; rstModule(); } sleep(CheckModemInfoInterval); } } else { DEBUG_ERROR("Device search error fail: %d\n", Dongle.cnt_SearchModuleFail); ShmStatusCodeData->InfoCode.InfoEvents.bits.InternetDisconnectVia4Gi = 1; ShmStatusCodeData->InfoCode.InfoEvents.bits.ApnDisconnectVia4Gi = 1; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.Telecom4GModuleCommFail = 0; ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomNetworkConn = 0; ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomRssi = 0; ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimStatus = 0; ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModemMode = 0; memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModemImei, 0, sizeof ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModemImei); memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimImsi, 0, sizeof ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimImsi); memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomIpAddress, 0, sizeof ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomIpAddress); memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimIccid, 0, sizeof ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimIccid); memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSoftwareVer, 0, sizeof ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSoftwareVer); memset(ShmSysConfigAndInfo->SysInfo.TelcomModemFwRev, 0, sizeof ShmSysConfigAndInfo->SysInfo.TelcomModemFwRev); memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModelName, 0, sizeof ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModelName); Dongle.cnt_SearchModuleFail++; if(Dongle.cnt_SearchModuleFail > 3) { DEBUG_ERROR("4G Module was broken.\n"); if(isModuleUnbind() == PASS) { isModuleBind(); } ShmStatusCodeData->FaultCode.FaultEvents.bits.Telecom4GModuleBroken = 1; Dongle.cnt_SearchModuleFail = 0; } sleep(CheckModemInterval); } break; case DISABLE_4G_MODULE: default: DEBUG_INFO("4G module : [ Disable ].\n"); ShmStatusCodeData->InfoCode.InfoEvents.bits.InternetDisconnectVia4Gi = 0; ShmStatusCodeData->InfoCode.InfoEvents.bits.ApnDisconnectVia4Gi= 0; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.Telecom4GModuleCommFail = 0; ShmStatusCodeData->FaultCode.FaultEvents.bits.Telecom4GModuleBroken = 0; ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomNetworkConn = 0; ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomRssi = 0; ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimStatus = 0; ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModemMode = 0; memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModemImei, 0, sizeof ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModemImei); memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimImsi, 0, sizeof ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimImsi); memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomIpAddress, 0, sizeof ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomIpAddress); memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimIccid, 0, sizeof ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimIccid); memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSoftwareVer, 0, sizeof ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSoftwareVer); memset(ShmSysConfigAndInfo->SysInfo.TelcomModemFwRev, 0, sizeof ShmSysConfigAndInfo->SysInfo.TelcomModemFwRev); memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModelName, 0, sizeof ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModelName); system("killall 4GDetection"); system("killall pppd"); system("ifconfig ppp0 down"); sleep(SystemInterval); break; } } return 0; }