Example #1
0
File: db.go Project: seka17/geo
// Find делает выборку из базы данных всех подходящих координат станций и возвращает их.
func (db DB) Find(req *Request) geo.Point {
	if req == nil || db == nil {
		return geo.NaNPoint
	}
	id := fmt.Sprintf("%d:%d", req.MCC, req.MNC) // формируем первичный ключ запроса
	sdb, ok := db[id]                            // получаем вложенный раздел базы
	if !ok {
		return geo.NaNPoint // вложенный раздел не найден
	}
	var sm, slat, slon float64
	// перебираем все данные о сетях
	for _, cell := range req.Cells {
		sid := fmt.Sprintf("%d:%d", cell.Area, cell.ID)
		points, ok := sdb[sid]
		if !ok {
			continue // игнорируем
		}
		// перебираем все доступные данные для станции
		for _, point := range points {
			m := math.Pow(10, (float64(cell.DBM)/20)) * 1000
			sm += m
			slat += point.Lat() * m
			slon += point.Lon() * m
		}
	}
	if sm == 0 {
		return geo.NaNPoint
	}
	return geo.NewPoint(slat/sm, slon/sm)
}
Example #2
0
File: db.go Project: seka17/geo
// ImportCSV импортирует данные из формата CSV.
// В данный момент захардкодено игнорирование первой строки (как заголовка) и всех данных,
// которые не относятся к сети GSM.
func ImportCSV(filename string) (DB, error) {
	log.Printf("Import DB from CSV %q", filename)
	file, err := os.Open(filename)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	db := make(DB)     // создаем новую базу данных
	var counter uint32 // счетчик
	r := csv.NewReader(file)
	for {
		record, err := r.Read()
		if err == io.EOF {
			break
		}
		if err != nil {
			return nil, err
		}
		counter++
		if counter == 1 {
			r.FieldsPerRecord = len(record) // устанавливаем количество полей
			continue                        // пропускаем первую строку с заголовком в CSV-файле
		}

		// фильруем базу данных: только GSM-станции
		// 250 - Россия, 255 - Украина, 257 - Беларусия
		if record[0] != "GSM" || !(record[1] == "250" || record[1] == "255" || record[1] == "257") {
			continue
		}

		id := strings.Join(record[1:3], ":") // уникальный идентификатор страны и кода оператора
		sdb, ok := db[id]                    // получаем вложенный раздел базы
		if !ok {
			sdb = make(map[string][]geo.Point) // инициализируем вложенный раздел
			db[id] = sdb
		}
		sid := strings.Join(record[3:5], ":") // уникальный идентификатор Cell Area и Base station number
		stdb, ok := sdb[sid]                  // получаем доступ к массиву данных для данной станции
		if !ok {
			stdb = make([]geo.Point, 0)
		}
		lng, err := strconv.ParseFloat(record[6], 64)
		if err != nil {
			log.Println("Bad longitude:", record[6])
			continue
		}
		lat, err := strconv.ParseFloat(record[7], 64)
		if err != nil {
			log.Println("Bad latitude:", record[7])
			continue
		}
		sdb[sid] = append(stdb, geo.NewPoint(lat, lng))
	}
	return db, nil
}
Example #3
0
File: main.go Project: seka17/geo
func main() {
	// TODO: по-хорошему, нужен, конечно, конфигурационный файл со всеми опциями
	log.Println("Connecting to NATS...")
	// подключаемся к NATS-серверу
	nc, err := nats.Connect("nats://" + natsServer)
	if err != nil {
		// потом убрать
		nc, err = nats.DefaultOptions.Connect()
		if err != nil {
			log.Println("Error NATS Connect:", err)
			return
		}

	}
	// TODO: добавить encoder сообщений (GOB?)
	defer nc.Close()

	// загружаем базу данных с гео-информацией по вышкам сотовой связи
	db, err := lbs.LoadDB("cells.gob")
	if err != nil {
		log.Println("Error loading GeoDB:", err)
		return
	}
	// добавляем подписку
	lbsSubs, err := nc.Subscribe(serviceNameLBS, func(msg *nats.Msg) {
		// пример строки с LBS:
		// 864078-35827-010003698-fa-2-1e50-772a-95-1e50-773c-a6-1e50-7728-a1-1e50-7725-92-1e50-772d-90-1e50-7741-90-1e50-7726-88
		req, err := lbs.Parse(string(msg.Data)) // разбираем полученные данные
		if err != nil {
			log.Println("Error parse LBS:", err)
			return
		}
		point := db.Find(req) // получаем точку по координатам
		if math.IsNaN(point.Lat()) || math.IsNaN(point.Lon()) {
			log.Println("Error searching LBS:", err)
			// TODO: наверное, нужно отдавать пустой ответ
			return
		}
		// отправляем ответ с данными
		if err := nc.Publish(msg.Reply, []byte(point.String())); err != nil {
			log.Println("Error Publish ephemeridos:", err)
		}
	})
	if err != nil {
		log.Println("Error NATS Subscribe:", err)
		return
	}
	defer lbsSubs.Unsubscribe()

	// инициализируем клиента для получения инициализационной информации о GPS
	client := ublox.NewClient("I6KKO4RU_U2DclBM9GVyrA")
	// добавляем профиль устройства: от этого зависит формат возвращаемых данных
	profile := ublox.Profile{
		Datatype:    []string{"eph"},
		Format:      "aid",
		FilterOnPos: true,
	}
	// инициализируем кеш для инициализационной информации о GPS
	cache := ublox.NewCache(client, profile, time.Minute*60, 200)
	// добавляем подписку
	ephSubs, err := nc.Subscribe(serviceNameEph, func(msg *nats.Msg) {
		// разбор данных
		var tmp MsgFromEph
		var point geo.Point
		if err = json.Unmarshal(msg.Data, &tmp); err != nil {
			//TODO: отправлять ошибку
			return
		}
		point = geo.NewPoint(tmp.Lat, tmp.Lon) // создаем координаты
		data, err := cache.Get(point)          // получаем данные из кеша
		if err != nil {
			log.Println("Error Get ephemeridos:", err)
			// TODO: наверное, нужно отдавать пустой ответ
			return
		}
		// отправляем ответ с данными
		if err := nc.Publish(msg.Reply, data); err != nil {
			log.Println("Error Publish ephemeridos:", err)
		}
	})
	if err != nil {
		log.Println("Error NATS Subscribe:", err)
		return
	}
	defer ephSubs.Unsubscribe()

	// ждем одного из сигналов...
	signal := moitorSignals(os.Interrupt, os.Kill)
	_ = signal

	log.Println("Disconnecting from NATS...")
}
Example #4
0
package ublox

import (
	"fmt"
	"testing"

	"github.com/mdigger/geo"
)

var (
	token     = "ADD_YOUR_TOKEN"
	pointWork = geo.NewPoint(55.715084, 37.57351)  // работа
	pointHome = geo.NewPoint(55.765944, 37.589248) // дом
)

func TestClient(t *testing.T) {
	ubox := NewClient(token)
	data, err := ubox.GetOnline(pointWork, DefaultProfile)
	if err != nil {
		t.Fatal(err)
	}
	fmt.Println(data)
	// data, err = ubox.GetOnline(pointHome, DefaultProfile)
	// if err != nil {
	// 	t.Fatal(err)
	// }
	// fmt.Println(data)
	// data, err = ubox.GetOnline(geotools.Point{}, DefaultProfile)
	// if err != nil {
	// 	t.Fatal(err)
	// }