From a8ac4bb2dffe2dfe8030ad9f34ec10a4f9684d54 Mon Sep 17 00:00:00 2001 From: Andreas.Eversberg Date: Sun, 24 Oct 2010 14:12:58 +0000 Subject: Introducing "gsmmap" to convert SYSTEM INFORMATION log into a KML map --- src/host/gsmmap/gsmmap.c | 646 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 646 insertions(+) create mode 100644 src/host/gsmmap/gsmmap.c (limited to 'src/host/gsmmap/gsmmap.c') diff --git a/src/host/gsmmap/gsmmap.c b/src/host/gsmmap/gsmmap.c new file mode 100644 index 0000000..01f3670 --- /dev/null +++ b/src/host/gsmmap/gsmmap.c @@ -0,0 +1,646 @@ +/* Conversion of logged cells to KML file */ + +/* (C) 2010 by Andreas Eversberg + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ +#warning todo bsic +#include +#include +#include +#include +#include +#include + +#define GSM_TA_M 553.85 +#define PI 3.1415926536 + +#include +#include + +#include "log.h" +#include "geo.h" +#include "locate.h" + +/* + * structure of power and cell infos + */ + +struct power power; +struct sysinfo sysinfo; +static struct node_power *node_power_first = NULL; +static struct node_power **node_power_last_p = &node_power_first; +struct node_mcc *node_mcc_first = NULL; +int log_lines = 0, log_debug = 0; + + +static void nomem(void) +{ + fprintf(stderr, "No mem!\n"); + exit(-ENOMEM); +} + +static void add_power() +{ + struct node_power *node_power; + +// printf("New Power\n"); + /* append or insert to list */ + node_power = calloc(1, sizeof(struct node_power)); + if (!node_power) + nomem(); + *node_power_last_p = node_power; + node_power_last_p = &node_power->next; + memcpy(&node_power->power, &power, sizeof(power)); +} + +static void add_sysinfo() +{ + struct gsm48_sysinfo s; + struct node_mcc *mcc; + struct node_mnc *mnc; + struct node_lac *lac; + struct node_cell *cell; + struct node_meas *meas; + + memset(&s, 0, sizeof(s)); + + /* decode sysinfo */ + if (sysinfo.si1[2]) + gsm48_decode_sysinfo1(&s, + (struct gsm48_system_information_type_1 *) sysinfo.si1, + 23); + if (sysinfo.si2[2]) + gsm48_decode_sysinfo2(&s, + (struct gsm48_system_information_type_2 *) sysinfo.si2, + 23); + if (sysinfo.si2bis[2]) + gsm48_decode_sysinfo2bis(&s, + (struct gsm48_system_information_type_2bis *) + sysinfo.si2bis, + 23); + if (sysinfo.si2ter[2]) + gsm48_decode_sysinfo2ter(&s, + (struct gsm48_system_information_type_2ter *) + sysinfo.si2ter, + 23); + if (sysinfo.si3[2]) + gsm48_decode_sysinfo3(&s, + (struct gsm48_system_information_type_3 *) sysinfo.si3, + 23); + if (sysinfo.si4[2]) + gsm48_decode_sysinfo4(&s, + (struct gsm48_system_information_type_4 *) sysinfo.si4, + 23); + + mcc = get_node_mcc(s.mcc); + if (!mcc) + nomem(); + mnc = get_node_mnc(mcc, s.mnc); + if (!mnc) + nomem(); + lac = get_node_lac(mnc, s.lac); + if (!lac) + nomem(); + cell = get_node_cell(lac, s.cell_id); + if (!cell) + nomem(); + meas = add_node_meas(cell); + if (!meas) + nomem(); + if (!cell->content) { + cell->content = 1; + memcpy(&cell->sysinfo, &sysinfo, sizeof(sysinfo)); + memcpy(&cell->s, &s, sizeof(s)); + } else { + if (memcmp(&cell->sysinfo.si1, sysinfo.si1, + sizeof(sysinfo.si1))) { +new_sysinfo: + fprintf(stderr, "FIXME: the cell changed sysinfo\n"); + return; + } + if (memcmp(&cell->sysinfo.si2, sysinfo.si2, + sizeof(sysinfo.si2))) + goto new_sysinfo; + if (memcmp(&cell->sysinfo.si2bis, sysinfo.si2bis, + sizeof(sysinfo.si2bis))) + goto new_sysinfo; + if (memcmp(&cell->sysinfo.si2ter, sysinfo.si2ter, + sizeof(sysinfo.si2ter))) + goto new_sysinfo; + if (memcmp(&cell->sysinfo.si3, sysinfo.si3, + sizeof(sysinfo.si3))) + goto new_sysinfo; + if (memcmp(&cell->sysinfo.si4, sysinfo.si4, + sizeof(sysinfo.si4))) + goto new_sysinfo; + } +} + +void kml_header(FILE *outfp, char *name) +{ + /* XML header */ + fprintf(outfp, "\n"); + + /* KML open tag */ + fprintf(outfp, "\n"); + + /* document open tag */ + fprintf(outfp, "\n"); + + /* pushpin */ + fprintf(outfp, "\t\n"); + fprintf(outfp, "\t\n"); + fprintf(outfp, "\t\n"); + fprintf(outfp, "\t\t\n"); + fprintf(outfp, "\t\t\tnormal\n"); + fprintf(outfp, "\t\t\t#sn_placemark_red_pushpin" + "\n"); + fprintf(outfp, "\t\t\n"); + fprintf(outfp, "\t\t\n"); + fprintf(outfp, "\t\t\thighlight\n"); + fprintf(outfp, "\t\t\t#sh_placemark_red_pushpin_highlight" + "\n"); + fprintf(outfp, "\t\t\n"); + fprintf(outfp, "\t\n"); + + fprintf(outfp, "\t\n"); + fprintf(outfp, "\t\n"); + fprintf(outfp, "\t\n"); + fprintf(outfp, "\t\t\n"); + fprintf(outfp, "\t\t\tnormal\n"); + fprintf(outfp, "\t\t\t#sn_placemark_grn_pushpin" + "\n"); + fprintf(outfp, "\t\t\n"); + fprintf(outfp, "\t\t\n"); + fprintf(outfp, "\t\t\thighlight\n"); + fprintf(outfp, "\t\t\t#sh_placemark_grn_pushpin_highlight" + "\n"); + fprintf(outfp, "\t\t\n"); + fprintf(outfp, "\t\n"); + + /* circle */ + fprintf(outfp, "\t\n"); + fprintf(outfp, "\t\n"); + fprintf(outfp, "\t\n"); + fprintf(outfp, "\t\t\n"); + fprintf(outfp, "\t\t\tnormal\n"); + fprintf(outfp, "\t\t\t#sn_placemark_circle\n"); + fprintf(outfp, "\t\t\n"); + fprintf(outfp, "\t\t\n"); + fprintf(outfp, "\t\t\thighlight\n"); + fprintf(outfp, "\t\t\t#sh_placemark_circle_highlight" + "\n"); + fprintf(outfp, "\t\t\n"); + fprintf(outfp, "\t\n"); +} + +void kml_footer(FILE *outfp) +{ + /* document close tag */ + fprintf(outfp, "\n"); + + /* KML close tag */ + fprintf(outfp, "\n"); + +} + +void kml_meas(FILE *outfp, struct node_meas *meas, int n, uint16_t mcc, + uint16_t mnc, uint16_t lac, uint16_t cellid) +{ + struct tm *tm = localtime(&meas->gmt); + + fprintf(outfp, "\t\t\t\t\t\n"); + fprintf(outfp, "\t\t\t\t\t\t%d: %d\n", n, meas->rxlev); + fprintf(outfp, "\t\t\t\t\t\t\n"); + fprintf(outfp, "MCC=%s MNC=%s\nLAC=%04x CELL-ID=%04x\n(%s %s)\n", + gsm_print_mcc(mcc), gsm_print_mnc(mnc), lac, cellid, + gsm_get_mcc(mcc), gsm_get_mnc(mcc, mnc)); + fprintf(outfp, "\n%s", asctime(tm)); + fprintf(outfp, "RX-LEV %d dBm\n", meas->rxlev); + if (meas->ta_valid) + fprintf(outfp, "TA=%d (%d-%d meter)\n", meas->ta, + (int)(GSM_TA_M * meas->ta), + (int)(GSM_TA_M * (meas->ta + 1))); + fprintf(outfp, "\t\t\t\t\t\t\n"); + fprintf(outfp, "\t\t\t\t\t\t\n"); + fprintf(outfp, "\t\t\t\t\t\t\t%.8f\n", + meas->longitude); + fprintf(outfp, "\t\t\t\t\t\t\t%.8f\n", + meas->latitude); + fprintf(outfp, "\t\t\t\t\t\t\t0\n"); + fprintf(outfp, "\t\t\t\t\t\t\t0\n"); + fprintf(outfp, "\t\t\t\t\t\t\trelativeToGround" + "\n"); + fprintf(outfp, "\t\t\t\t\t\t\trelativeToSeaFloor" + "\n"); + fprintf(outfp, "\t\t\t\t\t\t\n"); + fprintf(outfp, "\t\t\t\t\t\t#msn_placemark_circle" + "\n"); + fprintf(outfp, "\t\t\t\t\t\t\n"); + fprintf(outfp, "\t\t\t\t\t\t\t%.8f,%.8f\n", + meas->longitude, meas->latitude); + fprintf(outfp, "\t\t\t\t\t\t\n"); + fprintf(outfp, "\t\t\t\t\t\n"); +} + +static void print_si(void *priv, const char *fmt, ...) +{ + char buffer[1000]; + FILE *outfp = (FILE *)priv; + va_list args; + + va_start(args, fmt); + vsnprintf(buffer, sizeof(buffer) - 1, fmt, args); + buffer[sizeof(buffer) - 1] = '\0'; + va_end(args); + + if (buffer[0]) + fprintf(outfp, "%s", buffer); +} + +double debug_long, debug_lat, debug_x_scale; +FILE *debug_fp; + +void kml_cell(FILE *outfp, struct node_cell *cell) +{ + struct node_meas *meas; + double x, y, z, sum_x = 0, sum_y = 0, sum_z = 0, longitude, latitude; + int n, known = 0; + + meas = cell->meas; + n = 0; + while (meas) { + if (meas->gps_valid && meas->ta_valid) { + geo2space(&x, &y, &z, meas->longitude, meas->latitude); + sum_x += x; + sum_y += y; + sum_z += z; + n++; + } + meas = meas->next; + } + if (!n) + return; + if (n < 3) { + x = sum_x / n; + y = sum_y / n; + z = sum_z / n; + space2geo(&longitude, &latitude, x, y, z); + } else { + struct probe *probe_first = NULL, *probe, + **probe_last_p = &probe_first; + double x_scale; + + /* translate to flat surface */ + meas = cell->meas; + x_scale = 1.0 / cos(meas->latitude / 180.0 * PI); + longitude = meas->longitude; + latitude = meas->latitude; + debug_x_scale = x_scale; + debug_long = longitude; + debug_lat = latitude; + debug_fp = outfp; + while (meas) { + if (meas->gps_valid && meas->ta_valid) { + probe = calloc(1, sizeof(struct probe)); + if (!probe) + nomem(); + probe->x = (meas->longitude - longitude) / + x_scale; + if (x < -180) + x += 360; + else if (x > 180) + x -= 360; + probe->y = meas->latitude - latitude; + probe->dist = GSM_TA_M * (0.5 + + (double)meas->ta) / + (EQUATOR_RADIUS * PI / 180.0); + *probe_last_p = probe; + probe_last_p = &probe->next; + } + meas = meas->next; + } + + /* locate */ + locate_cell(probe_first, &x, &y); + + /* translate from flat surface */ + longitude += x * x_scale; + if (longitude < 0) + longitude += 360; + else if (longitude >= 360) + longitude -= 360; + latitude += y; + + /* remove probes */ + while (probe_first) { + probe = probe_first; + probe_first = probe->next; + free(probe); + } + + known = 1; + } + + if (!known) + return; + + fprintf(outfp, "\t\t\t\t\t\n"); + fprintf(outfp, "\t\t\t\t\t\tMCC=%s MNC=%s\nLAC=%04x " + "CELL-ID=%04x\n(%s %s)\n", gsm_print_mcc(cell->s.mcc), + gsm_print_mnc(cell->s.mnc), cell->s.lac, cell->s.cell_id, + gsm_get_mcc(cell->s.mcc), + gsm_get_mnc(cell->s.mcc, cell->s.mnc)); + fprintf(outfp, "\t\t\t\t\t\t\n"); + gsm48_sysinfo_dump(&cell->s, cell->sysinfo.arfcn, print_si, outfp); + fprintf(outfp, "\t\t\t\t\t\t\n"); + fprintf(outfp, "\t\t\t\t\t\t\n"); + fprintf(outfp, "\t\t\t\t\t\t\t%.8f\n", + longitude); + fprintf(outfp, "\t\t\t\t\t\t\t%.8f\n", latitude); + fprintf(outfp, "\t\t\t\t\t\t\t0\n"); + fprintf(outfp, "\t\t\t\t\t\t\t0\n"); + fprintf(outfp, "\t\t\t\t\t\t\trelativeToGround" + "\n"); + fprintf(outfp, "\t\t\t\t\t\t\trelativeToSeaFloor" + "\n"); + fprintf(outfp, "\t\t\t\t\t\t\n"); + if (known) + fprintf(outfp, "\t\t\t\t\t\t#msn_placemark_grn_" + "pushpin\n"); + else + fprintf(outfp, "\t\t\t\t\t\t#msn_placemark_red_" + "pushpin\n"); + fprintf(outfp, "\t\t\t\t\t\t\n"); + fprintf(outfp, "\t\t\t\t\t\t\t%.8f,%.8f\n", + longitude, latitude); + fprintf(outfp, "\t\t\t\t\t\t\n"); + fprintf(outfp, "\t\t\t\t\t\n"); + + if (!log_lines) + return; + + fprintf(outfp, "\t\n"); + fprintf(outfp, "\t\tLines\n"); + fprintf(outfp, "\t\t0\n"); + fprintf(outfp, "\t\t0\n"); + + geo2space(&x, &y, &z, longitude, latitude); + meas = cell->meas; + n = 0; + while (meas) { + if (meas->gps_valid) { + double mx, my, mz, dist; + + geo2space(&mx, &my, &mz, meas->longitude, + meas->latitude); + dist = distinspace(x, y, z, mx, my, mz); + fprintf(outfp, "\t\t\n"); + fprintf(outfp, "\t\t\tRange\n"); + fprintf(outfp, "\t\t\t\n"); + fprintf(outfp, "Distance: %d\n", (int)dist); + fprintf(outfp, "TA=%d (%d-%d meter)\n", meas->ta, + (int)(GSM_TA_M * meas->ta), + (int)(GSM_TA_M * (meas->ta + 1))); + fprintf(outfp, "\t\t\t\n"); + fprintf(outfp, "\t\t\t0\n"); + fprintf(outfp, "\t\t\t\n"); + fprintf(outfp, "\t\t\t\t1\n"); + fprintf(outfp, "\t\t\t\t\n"); + fprintf(outfp, "%.8f,%.8f\n", longitude, latitude); + fprintf(outfp, "%.8f,%.8f\n", meas->longitude, + meas->latitude); + fprintf(outfp, "\t\t\t\t\n"); + fprintf(outfp, "\t\t\t\n"); + fprintf(outfp, "\t\t\n"); + } + meas = meas->next; + } + fprintf(outfp, "\t\n"); +} + +int main(int argc, char *argv[]) +{ + FILE *infp, *outfp; + int type, n, i; + char *p; + struct node_mcc *mcc; + struct node_mnc *mnc; + struct node_lac *lac; + struct node_cell *cell; + struct node_meas *meas; + + if (argc <= 2) { +usage: + fprintf(stderr, "Usage: %s " + "[lines] [debug]\n", argv[0]); + fprintf(stderr, "lines: Add lines between cell and " + "Measurement point\n"); + fprintf(stderr, "debug: Add debugging of location algorithm.\n" + ); + return 0; + } + + for (i = 3; i < argc; i++) { + if (!strcmp(argv[i], "lines")) + log_lines = 1; + else if (!strcmp(argv[i], "debug")) + log_debug = 1; + else goto usage; + } + + infp = fopen(argv[1], "r"); + if (!infp) { + fprintf(stderr, "Failed to open '%s' for reading\n", argv[1]); + return -EIO; + } + + while ((type = read_log(infp))) { + switch (type) { + case LOG_TYPE_SYSINFO: + add_sysinfo(); + break; + case LOG_TYPE_POWER: + add_power(); + break; + } + } + + fclose(infp); + + if (!strcmp(argv[2], "-")) + outfp = stdout; + else + outfp = fopen(argv[2], "w"); + if (!outfp) { + fprintf(stderr, "Failed to open '%s' for writing\n", argv[2]); + return -EIO; + } + + /* document name */ + p = argv[2]; + while (strchr(p, '/')) + p = strchr(p, '/') + 1; + + kml_header(outfp, p); + mcc = node_mcc_first; + while (mcc) { + printf("MCC: %02x\n", mcc->mcc); + /* folder open */ + fprintf(outfp, "\t\n"); + fprintf(outfp, "\t\tMCC %s (%s)\n", + gsm_print_mcc(mcc->mcc), gsm_get_mcc(mcc->mcc)); + fprintf(outfp, "\t\t0\n"); + mnc = mcc->mnc; + while (mnc) { + printf(" MNC: %02x\n", mnc->mnc); + /* folder open */ + fprintf(outfp, "\t\t\n"); + fprintf(outfp, "\t\t\tMNC %s (%s)\n", + gsm_print_mnc(mnc->mnc), gsm_get_mnc(mcc->mcc, mnc->mnc)); + fprintf(outfp, "\t\t\t0\n"); + lac = mnc->lac; + while (lac) { + printf(" LAC: %04x\n", lac->lac); + /* folder open */ + fprintf(outfp, "\t\t\t\n"); + fprintf(outfp, "\t\t\t\tLAC %04x\n", lac->lac); + fprintf(outfp, "\t\t\t\t0\n"); + cell = lac->cell; + while (cell) { + printf(" CELL: %04x\n", cell->cellid); + fprintf(outfp, "\t\t\t\t\n"); + fprintf(outfp, "\t\t\t\t\tCELL-ID %04x\n", cell->cellid); + fprintf(outfp, "\t\t\t\t\t0\n"); + meas = cell->meas; + n = 0; + while (meas) { + if (meas->ta_valid) + printf(" TA: %d\n", meas->ta); + if (meas->gps_valid) + kml_meas(outfp, meas, ++n, mcc->mcc, mnc->mnc, + lac->lac, cell->cellid); + meas = meas->next; + } + kml_cell(outfp, cell); + /* folder close */ + fprintf(outfp, "\t\t\t\t\n"); + cell = cell->next; + } + /* folder close */ + fprintf(outfp, "\t\t\t\n"); + lac = lac->next; + } + /* folder close */ + fprintf(outfp, "\t\t\n"); + mnc = mnc->next; + } + /* folder close */ + fprintf(outfp, "\t\n"); + mcc = mcc->next; + } +#if 0 + FIXME: power + /* folder open */ + fprintf(outfp, "\t\n"); + fprintf(outfp, "\t\tPower\n"); + fprintf(outfp, "\t\t0\n"); + power = node_power_first; + n = 0; + while (power) { + /* folder open */ + fprintf(outfp, "\t\t\n"); + fprintf(outfp, "\t\t\tPower %d\n", ++n); + fprintf(outfp, "\t\t\t0\n"); + /* folder close */ + fprintf(outfp, "\t\t\n"); + power = power->next; + } + /* folder close */ + fprintf(outfp, "\t\n"); +#endif + kml_footer(outfp); + + fclose(outfp); + + return 0; +} -- cgit v1.2.3-55-g7522