no way to compare when less than two revisions

Differences

This shows you the differences between two versions of the page.


sdk:scripts:dynamic-operator [2015/05/05 15:04] (current) – created - external edit 127.0.0.1
Line 1: Line 1:
 +====== SDK Script dynamic-operator.are ======
 +<code c dynamic-operator.are>
 +/* DESC: This script will scan Mobile2 and dial the appropriate SIM on Mobile1
 + * Copyright (C) 2013 NetModule AG, Switzerland
 + *
 + */
 +
 +template operator {
 +    prio;
 +    sim;
 +    lai;
 +    apn;
 +    username;
 +    password;
 +
 +    int operator (int p, int s, string l, string a, string usr, string pwd) {
 +        this.prio = p;
 +        this.sim = s;
 +        this.lai = l;
 +        this.apn = a;
 +        this.username = usr;
 +        this.password = pwd;
 +        return 0;
 +    }
 +};
 +
 +ME = argv[0];           /* script path */
 +ARGV1 = argv[1];        /* 1st script argument */
 +FORCE = 0;              /* force operator switch even if wanlink is up */
 +VALID_ONLY = 1;         /* only register to networks which are allowed by SIM */
 +SCAN_INTERVAL = 30;     /* network scan interval in seconds */
 +TEST = 0;               /* run test */
 +
 +/* example list of operators */
 +OPCNT = 0;
 +OPERATORS = mkarray();
 +
 +OPERATORS[OPCNT++] = new operator
 +                        (1,                             /* prio */
 +                         0,                             /* SIM1 */
 +                         "22801",                       /* lai */
 +                         "corporate.swisscom.ch",       /* apn */
 +                         "testprofil",                  /* username */
 +                         "temporary"                    /* password */
 +                        );
 +OPERATORS[OPCNT++] = new operator
 +                        (2,                             /* prio */
 +                         1,                             /* SIM2 */
 +                         "22802",                       /* lai */
 +                         "internet",                    /* apn */
 +                         "internet",                    /* username */
 +                         "internet"                     /* password */
 +                        );
 +OPERATORS[OPCNT++] = new operator
 +                        (3,                             /* prio */
 +                         2,                             /* EXT1 */
 +                         "26201",                       /* lai */
 +                         "internet.telekom",            /* apn */
 +                         "tm",                          /* username */
 +                         ""                             /* password */
 +                        );
 +
 +
 +/* creates file at path */
 +int touch (string path)
 +{
 +    fd = open(path, O_CREAT | O_WRONLY);
 +    if (fd < 0) return -1;
 +    close(fd);
 +    return 0;
 +}
 +
 +/* checks if path exists */
 +int exists (string path)
 +{
 +    fd = open(path, O_RDONLY);
 +    if (fd < 0) return 0;
 +    close(fd);
 +    return 1;
 +}
 +
 +/* copies a file */
 +int copy (string from, string to)
 +{
 +    fpin = fopen(from, "r");
 +    if (is_void(fpin)) {
 +        nb_syslog("unable to open %s", from);
 +        return -1;
 +    }
 +    fpout = fopen(to, "w+");
 +    if (is_void(fpout)) {
 +        fclose(fpin);
 +        nb_syslog("unable to open %s", to);
 +        return -1;
 +    }
 +    while (1) {
 +        buf = fread(fpin, 1024);
 +        if (is_void(buf)) break;
 +
 +        len = strlen(buf);
 +        if (len == 0) break;
 +    
 +        fwrite(fpout, buf, len);
 +    }
 +    fclose(fpin);
 +    fclose(fpout);
 +
 +    return 0;
 +}
 +
 +/* mkdir -p */
 +int makedir (string path, int mode)
 +{
 +    pc = explode(path);
 +
 +    if (pc[0] != "/") {
 +        nb_syslog("no absolute directory given");
 +        return -1;
 +    }
 +
 +    len = length(pc);
 +    if (pc[len-1] != "/") pc[len++] = "/";
 +    p = "";
 +
 +    for (i = 0; i < len; i++) {
 +        if (pc[i] == "/" && i > 0) {
 +            mkdir(p, mode);
 +        }
 +        p = strcat(p, pc[i]);
 +    }
 +
 +    return 0;
 +}
 +
 +/* returns operator index for specified lai */
 +int find_operator (string lai)
 +{
 +    if (lai != "") {
 +        /* search by lai first */
 +        for (o = 0; o < OPCNT; o++) {
 +            if (OPERATORS[o].lai == lai) return o;
 +        }
 +    }
 +
 +    return -1; /* not a known operator */
 +}
 +
 +/* returns wwan interface index for specified sim index */
 +int find_wwan_interface (int sim)
 +{
 +    for (o = 0; o < OPCNT; o++) {
 +        op = OPERATORS[o];
 +
 +        if (op.sim == sim) {
 +            return o;
 +        }
 +    }
 +    return -1; /* no wwan interface with this sim */
 +}
 +
 +/* returns current wwan interface index */
 +int current_operator ()
 +{
 +    n = nb_config_get("wanlink.0.name");
 +    if (strlen(n) >= 5 && left(n, 4) == "wwan") {
 +        return (int)substr(n, 4, 1);
 +    }
 +
 +    return -1; /* not configured */
 +}
 +
 +/* activates specified operator */
 +int activate_operator (int op)
 +{
 +    current = current_operator();
 +
 +    if (current != -1 && current == op) {
 +        nb_syslog("wwan%d is already active", op);
 +        return 0;
 +    }
 +    nb_syslog("switching to wwan%d", op);
 +
 +    if (nb_config_set(sprintf("wanlink.0.name=wwan%d", op)) != 0) {
 +        nb_syslog("unable to activate wwan%d", op);
 +        return -1;
 +    }
 +    /* re-configuration triggered */
 +    nb_syslog("activated wwan%d", op);
 +
 +    /* give modem some time to register */
 +    nb_syslog("waiting for wwan%d to come up", op);
 +    sleep(30); /* needed for SIM switch */
 +
 +    /* wait for wanlink to come up */
 +    for (i = 0; i < 20; i++) {
 +        sleep(10);
 +
 +        nb_syslog("checking if wwan%d has come up", op);
 +        st = nb_status("wan");
 +
 +        ifc = struct_get(st, "WANLINK1_INTERFACE");
 +        if (ifc != sprintf("WWAN%d", op+1)) {
 +            nb_syslog("wwan%d is not yet active");
 +            continue;
 +        }
 +        state = struct_get(st, "WANLINK1_STATE");
 +        if (state == "up") {
 +            nb_syslog("wwan%d is up now", op);
 +            return 0;
 +        }
 +        attempts = (int) struct_get(st, "WANLINK1_DIAL_ATTEMPTS");
 +        nb_syslog("wwan%d has dialed for %d times", op, attempts);
 +        if (attempts > 2) {
 +            nb_syslog("giving up after %d dial attempts", attempts);
 +            return -1;
 +        }
 +    }
 +    nb_syslog("giving up waiting for wanlink");
 +
 +    return 0;
 +}
 +
 +/* returns true if wanlink is up */
 +bool wanup ()
 +{
 +    st = nb_status("wan");
 +    state = struct_get(st, "WANLINK1_STATE");
 +    return (state == "up");
 +}
 +
 +/* scan test */
 +struct nb_scan_test ()
 +{
 +    return mkstruct(
 +        "NETWORK_COUNT", 2,
 +
 +        "NETWORK1_NAME", "swisscom",
 +        "NETWORK1_LAI", "22801",
 +        "NETWORK1_STATUS", "available",
 +
 +        "NETWORK2_NAME", "telekom",
 +        "NETWORK2_LAI", "26201",
 +        "NETWORK2_STATUS", "available"
 +    );
 +}
 +
 +/* installs config and script */
 +int install ()
 +{
 +    path = "/config";
 +    cfg = sprintf("%s/user-config.cfg", path);
 +
 +    makedir(sprintf("%s/files", path), S_IRUSR|S_IWUSR|S_IXUSR);
 +
 +    touch(cfg);
 +    fp = fopen(cfg, "w");
 +    if (!fp) {
 +        printf("ERROR: unable to open %s\n", cfg);
 +        return -1;
 +    }
 +
 +    /* basic system config */
 +    fwrite(fp, "config.version=1.3\n");
 +    fwrite(fp, sprintf("admin.password=%s\n", nb_config_get("admin.password")));
 +
 +    /* set up OPERATORS */
 +    for (o = 0; o < OPCNT; o++) {
 +        op = OPERATORS[o];
 +        fwrite(fp, sprintf("sim.%d.lai=%s\n", op.sim, op.lai));
 +        fwrite(fp, sprintf("wwan.%d.status=1\n", o));
 +        fwrite(fp, sprintf("wwan.%d.card=0\n", o));  /* force wwan0 */
 +        fwrite(fp, sprintf("wwan.%d.sim=%d\n", o, op.sim));
 +        fwrite(fp, sprintf("wwan.%d.number=*99***1#\n", o));
 +        fwrite(fp, sprintf("wwan.%d.username=%s\n", o, op.usename));
 +        fwrite(fp, sprintf("wwan.%d.password=%s\n", o, op.password));
 +        fwrite(fp, sprintf("wwan.%d.apn=%s\n", o, op.apn));
 +    }
 +
 +    /* enable first wwan interface */
 +    fwrite(fp, "wanlink.0.name=wwan0\n");
 +    fwrite(fp, "wanlink.0.prio=1\n");
 +    fwrite(fp, "wanlink.0.weight=0\n");
 +    fwrite(fp, "wanlink.0.mode=1\n");
 +
 +    /* install this script */
 +    fwrite(fp, "sdk.status=1\n");
 +    fwrite(fp, "sdk.trigger.0.name=SDK-STARTUP\n");
 +    fwrite(fp, "sdk.trigger.0.event=sdk-startup\n");
 +    fwrite(fp, "sdk.script.0.name=dynamic-operator\n");
 +    fwrite(fp, "sdk.job.0.name=DYNAMIC-OPERATOR\n");
 +    fwrite(fp, "sdk.job.0.trigger=0\n");
 +    fwrite(fp, "sdk.job.0.script=0\n");
 +
 +    scriptpath = sprintf("%s/files/home/sdk/scripts/uploaded", path);
 +    makedir(scriptpath, S_IRUSR|S_IWUSR|S_IXUSR);
 +    fclose(fp);
 +
 +    if (copy(ME, sprintf("%s/dynamic-operator", scriptpath)) != 0) {
 +        printf("ERROR: cannot copy script");
 +        return -1;
 +    }
 +
 +    return nb_update_config(sprintf("dir://%s", path));
 +}
 +
 +
 +/* -------------------------------- main -------------------------------- */
 +
 +nb_syslog("starting %s", ME);
 +
 +
 +if (ARGV1 == "install") {
 +    /* script installation requested */
 +    printf("installing script and its config\n");
 +
 +    if (install() != 0) {
 +        printf("unable to install script\n");
 +        exit(1);
 +    } else {
 +        printf("successfully installed script\n");
 +    }
 +    /* script will terminate at this point */
 +    exit(0);
 +
 +
 +/* re-read operators */
 +OPCNT = 0;
 +OPERATORS = mkarray();
 +
 +for (i = 0; i < 14; i++) {
 +    status = nb_config_get(sprintf("wwan.%d.status", i));
 +    if (status != "1") {
 +        continue;
 +    }
 +
 +    sim = nb_config_get(sprintf("wwan.%d.sim", i));
 +    if (sim < 0) {
 +        nb_syslog("invalid sim for wwan%d", i);
 +        continue;
 +    }
 +
 +    lai = nb_config_get(sprintf("sim.%d.lai", sim));
 +
 +    OPERATORS[OPCNT].prio = i;
 +    OPERATORS[OPCNT].lai = lai;
 +    OPERATORS[OPCNT].sim = sim;
 +    OPERATORS[OPCNT].username = nb_config_get(sprintf("wwan.%d.username", i));
 +    OPERATORS[OPCNT].password = nb_config_get(sprintf("wwan.%d.password", i));
 +    OPERATORS[OPCNT].apn = nb_config_get(sprintf("wwan.%d.apn", i));
 +
 +    nb_syslog("added operator%d (prio %d, sim %d, lai %s)", 
 +                OPCNT, i, sim, lai);
 +
 +    OPCNT++;
 +}
 +
 +while (1) {
 +    nb_syslog("sleeping");
 +    sleep(SCAN_INTERVAL);
 +
 +    /* get wanlink state */
 +    up = wanup();
 +    if (up) {
 +        nb_syslog("wanlink is up");
 +    } else {
 +        nb_syslog("wanlink is down");
 +    }
 +
 +    /* get current operator */
 +    current = current_operator();
 +    if (current != -1) {
 +        nb_syslog("current is wwan%d", current);
 +    }
 +
 +    if (up && current != -1) {
 +        nb_syslog("wwan%d is up", current);
 +        if (FORCE != 1) continue;
 +    }
 +
 +    /* scan networks */
 +    nb_syslog("scanning networks");
 +    if (TEST == 1) {
 +        nets = nb_scan_test();
 +    } else {
 +        nets = nb_scan_networks("Mobile2");
 +    }
 +    nr_nets = struct_get(nets, "NETWORK_COUNT");
 +
 +    if (is_void(nr_nets) || nr_nets < 1) {
 +        nb_syslog("no networks found");
 +        continue;
 +    }
 +
 +    nb_syslog("%d networks found", nr_nets);
 +
 +    best = -1;
 +    prio = -1;
 +    for (i = 1; i <= nr_nets; i++) {
 +        net = trim(struct_get(nets, sprintf("NETWORK%d_NAME", i)));
 +        lai = trim(struct_get(nets, sprintf("NETWORK%d_LAI", i)));
 +        status = trim(struct_get(nets, sprintf("NETWORK%d_STATUS", i)));
 +
 +        nb_syslog("detected network '%s' (lai %s, status %s)", net, lai, status);
 +
 +        if (VALID_ONLY == 1 && status != "available") continue;
 +
 +        op = find_operator(lai, net);
 +        if (op == -1) {
 +            nb_syslog("network '%s' does not belong to a known operator", net);
 +            continue;
 +        }
 +        if (current != -1 && op == current) {
 +            /* skip current operator */
 +            continue;
 +        }
 +        if (prio == -1 || OPERATORS[op].prio < prio) {
 +            best = op;
 +            prio = OPERATORS[op].prio;
 +        }
 +    }
 +    if (best != -1) {
 +        /* activate best operator */
 +        activate_operator(best);
 +    } else {
 +        nb_syslog("no better operator found");
 +    }
 +}
 +
 +exit(0);
 +
 +</code>