Connection Statistics

The data collected by this script can be used for many purposes including generating maps of network coverage, determining the quality of your connection at any given time and analyzing how often you’re Connecting or Roaming.

logger.are

Queries the cli status and logs items you are interested in into a comma separated values file, which can be accessed from anywhere with an internet connection.
Values are written to a comma-separated file e.g./home/sdk/sandbox/logger/current.csv
When the script restarts or when its time limit is reached, a new file will be created.
				
					    template logger {
        workfile="current.csv";
        serialNumber=nb_status('system').SERIAL_NUMBER;
        currentFilename="";
        currentLogStart=0; // the current logfile was startet at this time
        intervall=5; // new logentry every # seconds
        logfileIntervall=3600; // new logfile every # seconds
        // due to the fact that we cannot see the amount of free space in the sdk
        // we need to improvise and add up the current filesizes   
        currentLogSize=0; // in Bytes
        maxLogSize=15000000;  // in Bytes
        freespace=1000000; // in Bytes
        # give the constructor the absolute path to store the Loggs into
        void logger(string path) {
            dh=opendir(path);    
            if(dh == -1) {
                if ( mkdir(path,0666) == -1 ); {
                    nb_syslog("Could not create dir: %s. Exiting",path);
                    exit(1);
                }
            } else {
            nb_syslog("directory already existent: %s", path);
            closedir(dh);
            }
            this.path = path;
            this.fields = mkarray();
            namepart=strftime("%Y%m%d_%H%M%S_start.csv",localtime(time()));
            this.currentFilename=sprintf("%s_%s",this.serialNumber, namepart);
        }
     
        int jiffy() {
            sys = sysinfo();
            u = struct_get(sys, "uptime");
     
            if (is_void(u) || u < 1) {
                return 0;
            } else {
                return u;
            }
        } 
     
        int addField(string fieldname) {
            if (strlen(fieldname) > 0 ) {
                this.fields = array_merge(this.fields, fieldname);
                return 0;
            } else {
                nb_syslog("Fieldname to short, not adding");
                return -1;
            }
        }
     
        int addFields(array localFields) {
           for (i=0; i < length(localFields); i++) {
                if (this.addField(localFields[i]) == -1 ) return -1;
           }   
        return 0;
     
        }
     
        int newLogfile() {
            // check if file if we have a work file an rename it to currentFile
            fd=fopen(sprintf("%s%s", this.path,this.workfile),"r" );
            if(fd) {
                // we have a current workfile lets rename it
                fclose(fd);
                if(!rename(sprintf("%s%s",this.path,this.workfile), sprintf("%s%s",this.path,this.currentFilename))){
                    nb_syslog("Could not rename %s to %s, %s will be deleted",this.workfile, this.currentFilename,this.workfile);
                    remove(sprintf("%s%s",this.path,this.workfile));  
                }
            } 
            //set new current Filename as we stored the old one away
            namepart=strftime("%Y%m%d_%H%M%S.csv",localtime(time()));
            this.currentFilename=sprintf("%s_%s",this.serialNumber,namepart);
            this.currentLogStart=this.jiffy();
            //creating Header   
            header="";
            for (i=0; i < length(this.fields); i++) {
                header=sprintf('%s%s;',header,this.fields[i]);   
            }   
     
            if(this.addLineToFile(header) == -1 ) {
                nb_syslog("writing of header to file: %s%s:", this.path,this.workfile);
                return -1;
            } else {
                return 0;
            }
        }
     
        int addLineToFile(string line) {
            fd=fopen(sprintf("%s%s", this.path,this.workfile),"a" );
            if (fd < 0 ) {
                nb_syslog("could not open file %s%s", this.path, this.workfile);
            }
     
            if(!fwrite(fd,sprintf("%s\n",line))) {
                nb_syslog("writing of line to file: %s%s:", this.path,this.workfile);
                fclose(fd);
                return -1;
            } else {
                fclose(fd);
                return 0;
            }
        } 
     
        int filesize(string file) {
            fd=fopen(file,"r");
            if (fd) {
                fseek(fd,-1);
                size=ftell(fd);
                fclose(fd);
                return size;
            } else {
                return -1;
            }
        }
     
     
        int logNow()  {
            //get current status output
            sections=mkarray("system","wan","wwan","wlan","gnss","lan","openvpn","ipsec","dio","license", "hotspot");
            status=mkstruct();
            for (i=0;i<length(sections);i++) {
                status=struct_merge(status,nb_status(sections[i]));
            }
     
            line="";
            for (i=0; i < length(this.fields); i++) {
                value=struct_get(status,this.fields[i]);
                if (strlen(value) == 0) {   
                    value=sprintf("n/a");
                }
                line=sprintf('%s%s;',line,value);   
            }
     
            if(this.addLineToFile(line) == -1 ) {
                nb_syslog("writing of line to file failed: %s%s:", this.path,this.workfile);
                return -1;
            } else {
                return 0;
            }
        }
     
        int logRotate() {
            // get all files in path
            nb_syslog("Starting Logrotate");
            files=mkarray();
            handle = opendir(this.path);
            if (handle != -1) {
                while ((entry = readdir(handle))) {
                    if (entry == ".") continue;
                    if (entry == "..") continue;
                    if (entry == this.workfile) continue;
                    files=array_merge(files,entry);
                }
                closedir(handle);
            } else {
                nb_syslog("cannot open directory %s", this.path);
            }
            // sort old to new
            qsort(files);
            // files=array_reverse(files);
            // get current filesizes
            this.currenLogSize=0;
            sizes=mkarray();
            for(i=0;i<length(files);i++){
                size[i]=this.filesize(sprintf("%s%s",this.path,files[i]));
                this.currentLogSize=this.currentLogSize+size[i]; 
            }
            nb_syslog("Current Logsize: %i byte",this.currentLogSize);
            //if we don't have enough space delete enough old ones to have enough space
        return 0;
        }
    } 
    // ######################################################
    // ######################################################
    // ######################################################
     
    l = new logger("/logger/");
    // Timestamp of the Logentry
    l.addField("SYSTEM_TIME");
     
     
    // GPS Fields
    l.addField("GNSS1_LONGITUDE");
    l.addField("GNSS1_LATITUDE");
    l.addField("GNSS1_SATELLITES_INVIEW");
     
     
    // LTE Connection Fields
    // Can be cloneed with MOBILE2 in case more LTE Connections are used
    // Arbitrary Strength Unit (ASU) https://en.wikipedia.org/wiki/Mobile_phone_signal#ASU
    l.addField("MOBILE1_SIGNAL_LEVEL");
    // received signal code power  https://en.wikipedia.org/wiki/Received_signal_code_power
    l.addField("MOBILE1_SIGNAL_RSCP");
    // Received signal strength indication https://en.wikipedia.org/wiki/Received_signal_strength_indication           
    l.addField("MOBILE1_SIGNAL_RSSI");          
    // Service Type: LTE/HSPA/3G/2G/EDGE        
    l.addField("MOBILE1_SERVICE_TYPE");
    // NETWORK ID of the LTE Network we are connected to
    l.addField("MOBILE1_LAI");
    // Area Code in  LTE Network
    l.addField("MOBILE1_LAC");
    // Cell ID we are connected to
    l.addField("MOBILE1_CID");
    // Is the SIM registered in Home or Roaming
    l.addField("MOBILE1_REGISTRATION_STATE");
     
     
    // WAN Data Connection field
    // Connection that is current default Gateway
    l.addField("WAN_HOTLINK");
    // Per WANLINK/LTE Connection:
    // Current State: up/down/dialin
    l.addField("WANLINK1_STATE");
    // Current upload and download rates 
    l.addField("WANLINK1_DOWNLOAD_RATE");
    l.addField("WANLINK1_UPLOAD_RATE");
    // Bytes that are already down- or uploaded.
    l.addField("WANLINK1_DATA_DOWNLOADED");
    l.addField("WANLINK1_DATA_UPLOADED");
     
    // WLAN Fields
    // WLAN Clients Attached to the Accesspoint
    l.addField("WLAN1_STATION_COUNT");
     
    l.newLogfile();
    l.intervall=5; // log every 5sec
    l.logfileIntervall=3600; // create a new file every 5 min
     
    // ######################################################
    // ######################################################
    // ######################################################
    // ######################################################
     
     
    while (true) {
        l.logNow();
        sleep(l.intervall);
        // lets see if we need a new logfile
        if (l.currentLogStart+l.logfileIntervall<l.jiffy()) {
           l.newLogfile();
           l.logRotate();
        }
    }
    exit(0);


				
			

log-data.csv

				
					SYSTEM_TIME;GNSS1_LONGITUDE;GNSS1_LATITUDE;GNSS1_SATELLITES_INVIEW;MOBILE1_SIGNAL;MOBILE1_SERVICE_TYPE;MOBILE1_LAI;MOBILE1_LAC;MOBILE1_CID;WAN_HOTLINK;WANLINK1_STATE;WANLINK1_DOWNLOAD_RATE;WANLINK1_UPLOAD_RATE;WANLINK1_DATA_DOWNLOADED;WANLINK1_DATA_UPLOADED;WLAN1_STATION_COUNT;
2015-03-17 11:50:12;n/a;n/a;n/a;-87;UMTS;22803;1B5F;216C6;WANLINK1;up;168;219;28560577;29223265;0;
2015-03-17 11:50:19;n/a;n/a;n/a;-87;UMTS;22803;1B5F;216C6;WANLINK1;up;168;219;28560577;29223265;0;
2015-03-17 11:50:25;n/a;n/a;n/a;-87;UMTS;22803;1B5F;216C6;WANLINK1;up;168;219;28560577;29223265;0;
2015-03-17 11:50:31;n/a;n/a;n/a;-87;UMTS;22803;1B5F;216C6;WANLINK1;up;168;219;28560577;29223265;0;
2015-03-17 11:50:36;n/a;n/a;n/a;-87;UMTS;22803;1B5F;216C6;WANLINK1;up;168;219;28560577;29223265;0;
2015-03-17 11:50:43;n/a;n/a;n/a;-87;UMTS;22803;1B5F;216C6;WANLINK1;up;168;219;28560577;29223265;0;
2015-03-17 11:50:49;n/a;n/a;n/a;-87;UMTS;22803;1B5F;216C6;WANLINK1;up;168;219;28560577;29223265;0;
2015-03-17 11:50:55;n/a;n/a;n/a;-87;UMTS;22803;1B5F;216C6;WANLINK1;up;168;219;28560577;29223265;0;
2015-03-17 11:51:01;n/a;n/a;n/a;-87;UMTS;22803;1B5F;216C6;WANLINK1;up;168;219;28560577;29223265;0;
2015-03-17 11:51:11;n/a;n/a;n/a;-87;UMTS;22803;1B5F;216C6;WANLINK1;up;0;0;28562684;29225261;0;
2015-03-17 11:51:17;n/a;n/a;n/a;-87;UMTS;22803;1B5F;216C6;WANLINK1;up;0;0;28562684;29225261;0;
2015-03-17 11:51:23;n/a;n/a;n/a;-87;UMTS;22803;1B5F;2B306;WANLINK1;up;0;0;28562684;29225261;0;
2015-03-17 11:51:29;n/a;n/a;n/a;-87;UMTS;22803;1B5F;2B306;WANLINK1;up;0;0;28562684;29225261;0;
2015-03-17 11:51:35;n/a;n/a;n/a;-87;UMTS;22803;1B5F;2B306;WANLINK1;up;0;0;28562684;29225261;0;
2015-03-17 11:51:41;n/a;n/a;n/a;-87;UMTS;22803;1B5F;2B306;WANLINK1;up;0;0;28562684;29225261;0;
2015-03-17 11:51:47;n/a;n/a;n/a;-87;UMTS;22803;1B5F;2B306;WANLINK1;up;0;0;28562684;29225261;0;
2015-03-17 11:51:53;n/a;n/a;n/a;-87;UMTS;22803;1B5F;2B306;WANLINK1;up;0;0;28562684;29225261;0;
2015-03-17 11:51:59;n/a;n/a;n/a;-87;UMTS;22803;1B5F;2B306;WANLINK1;up;0;0;28562684;29225261;0;
2015-03-17 11:52:05;n/a;n/a;n/a;-87;UMTS;22803;1B5F;2B306;WANLINK1;up;0;0;28562684;29225261;0;
				
			

upload.are

				
					
     
    template uploader {   
        workfile="current.csv";
        path="";
        removefilesafterupload=false;
        server="";
        serverpath="/";
        user="";
        password="";
     
        void uploader(string path) {
            dh=opendir(path);    
            if(dh == -1) {
               nb_syslog("path %s not existent, exiting",path);     
               exit(1);           
            } else {
                nb_syslog("uploader path: %s", path);
                closedir(dh);
            }
            this.path = path;
        }
     
        int uploadfiles() {
            nb_syslog("starting uploading");
            files=mkarray();
            handle = opendir(this.path);
            if (handle != -1) {
                while ((entry = readdir(handle))) {
                    if (entry == ".") continue;
                    if (entry == "..") continue;
                    if (entry == this.workfile) continue;
                    files=array_merge(files,entry);
                }
                closedir(handle);
            } else {
                nb_syslog("cannot open directory %s", this.path);
            }
            // sort old to new
            qsort(files);
            // get current filesizes
            dump(files);
            for(i=0;i<length(files);i++){
                // lets upload every file
                if (nb_transfer_put(this.user, this.password, sprintf("%s/%s/%s", this.server, this.serverpath,files[i]), sprintf("%s%s",this.path,files[i])) == 0) {
                    nb_syslog("stored '%s%s' on remote site", this.path, files[i]);
                    if(this.removefilesafterupload) {
                        if(remove(sprintf("%s%s",this.path,files[i]))) {
                            nb_syslog("file %s%s removed after upload", this.path, files[i]);
                        } else {
                            nb_syslog("file %s%s can't be removed after upload", this.path, files[i]);
                        }
                    }
                } else {
                    nb_syslog("upload of '%s%s' was not successfull ", this.path, files[i]);
                }
            }
        return 0;
        }
    } // of template uploader
     
     
    ########### The real program ###############
     
    u = new uploader("/logger/");
    u.server="https://share.netmodule.com/router/public";
    u.serverpath="/logger/";
    u.user="*******";
    u.password="*******";
    u.removefilesafterupload=true;
    u.uploadfiles();