работа с OSM картами (QGIS) в среде Compact Framework

Разрабатывая очередное приложение, наткнулся на проблему связанную с открытием карт созданных в системе QGIS на мобильном устройстве с системой Windows Mobile. Проблему решил в течении 2-х недель. Кому это интересно пишете, с радостью отвечу. Почему не пишу сразу? Тема очень обширная, будет вопрос будет ответ. Классы разработанные мной можно переписать и для Phone 7 и для Android.

Класс для работы с INI - файлами в С#

Столкнулся с проблемой отсутствия инструмента для работы с INI-файлами в C#. Решил написать класс для работы с этими файлами и вчера вечером написал. Сильно не ругайте недостатков много. Буду подправлять постепенно. На данном этапе он меня устраивает, так как выполняет все необходимые мне функции и работает на Windows Mobile.


using System;
using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Windows.Forms;

namespace GUIDE
{
    public class INISection
    {
        public string INISectionName;
        public List<string> INIParametr;
        public List<string> INIValue;

        public INISection()
        {
            INIParametr = new List<string>();
            INIValue = new List<string>();
        }
    }

    public class CfgIni
    {

        StreamReader sr = null;
        StreamWriter sw = null;
        FileStream fs = null;
        List<INISection> sections;
        string file;

        public CfgIni(string FileName)
        {
            file = FileName;
            sections = new List<INISection>();
            ParseIniFile();
        }
        //********** ********** ********** ********** ********** ********** ********** ********** **********
        public void Close()
        {
            sections = null;
        }
        //********** ********** ********** ********** ********** ********** ********** ********** **********
        public void AddParametr(string section_name, string parametr_name, string value)
        {
            //создаем нувую строку параметров для секции по ее имени
            int index = GetSectionIndex(section_name);
            if (index != -1) { CreateParametr(index, parametr_name, value); }
        }
        //********** ********** ********** ********** ********** ********** ********** ********** **********
        public void CreateParametr(int section_index, string parametr_name, string value)
        {
            //создаем нувую строку параметров для секции по ее индексу
            if (!sections[section_index].INIParametr.Contains(parametr_name))
                {
                    sections[section_index].INIParametr.Add(parametr_name);
                    sections[section_index].INIValue.Add(value);
                    SaveIniFile();
                }
        }
        //********** ********** ********** ********** ********** ********** ********** ********** **********
        public int CreateSection(string section_name)
        {
            //создаем новую секцию
            int i = 0;
            bool flag = false;
            while (i != sections.Count)
            {
                if (sections[i].INISectionName == section_name)
                {
                    flag = true;
                }
            }
            if (!flag)
            {
                INISection section = new INISection();
                section.INISectionName = section_name;
                sections.Add(section);
                SaveIniFile();
                return sections.Count - 1;
            }
            else return -1;

        }
        //********** ********** ********** ********** ********** ********** ********** ********** **********
        public void SaveIniFile()
        {
            //сохраняем изменения в файл
            try
            {
                fs = new FileStream(file, FileMode.Create);
                sw = new StreamWriter(fs);

                int i = 0;
                while (i != sections.Count)
                {
                    sw.WriteLine("[" + sections[i].INISectionName + "]");
                    int j = 0;
                    while (j != sections[i].INIParametr.Count)
                    {
                        sw.WriteLine(sections[i].INIParametr[j] + "=" + sections[i].INIValue[j]);
                        j++;
                    }
                    i++;
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
            finally
            {
                sw.Dispose();
                fs.Dispose();
            }
        }
        //********** ********** ********** ********** ********** ********** ********** ********** **********
        public void UpdateValue(string section, string parametr_name, string value)
        {
            //устанваливаем значение Value в секцию Section в параметр с именем Name
            int i = 0;
            while (i != sections.Count)
            {
                if (sections[i].INISectionName == section)
                {
                    int j = 0;
                    while (j != sections[i].INIParametr.Count)
                    {
                        if (sections[i].INIParametr[j] == parametr_name)
                        {
                            sections[i].INIValue[j] = value;
                        }
                        j++;
                    }
                }
                i++;
            }
            SaveIniFile();
        }
        //********** ********** ********** ********** ********** ********** ********** ********** **********
        public string GetIniData(string section, string parametr_name)
        {
            //получаем значение Value параметра Name из секции Section
            string Value = null;
            int i = 0;
            while (i != sections.Count)
            {
                if (sections[i].INISectionName == section)
                {
                    int j = 0;
                    while (j != sections[i].INIParametr.Count)
                    {
                        if (sections[i].INIParametr[j] == parametr_name)
                        {
                            Value = sections[i].INIValue[j];
                        }
                        j++;
                    }
                }
                i++;
            }
            return Value;
        }
        //********** ********** ********** ********** ********** ********** ********** ********** **********
        public int GetSectionIndex(string section_name)
        {
            //возвращаем индекс секции по ее имени
            int i = 0;
            while (i != sections.Count)
            {
                if (sections[i].INISectionName == section_name)
                {
                    return i;
                }
                i++;
            }
            return -1;
        }
        //********** ********** ********** ********** ********** ********** ********** ********** **********
        public string GetSectionName(int index)
        {
            //возврашает имя секции INI - файла по индексу
            string result = null;
            try
            {
                result = sections[index].INISectionName;
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
            return result;
        }
        //********** ********** ********** ********** ********** ********** ********** ********** **********
        public string GetParametrName(int section_index, int parametr_index)
        {
            //возврашает имя параметра в секции по индексу секции INI-файла и индексу параметра
            string result = null;
            try
            {
                result = sections[section_index].INIParametr[parametr_index];
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
            return result;
        }
        //********** ********** ********** ********** ********** ********** ********** ********** **********
        public string GetParametrName(string section, int parametr_index)
        {
            //возврашает имя параметра в секции по названию секции INI-файла и индексу параметра
            int i = 0;
            string result = null;
            try
            {
                while (i != sections.Count)
                {
                    if (sections[i].INISectionName == section)
                    {
                        result = sections[i].INIParametr[parametr_index];
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
            return result;
        }
        //********** ********** ********** ********** ********** ********** ********** ********** **********
        public void ParseIniFile()
        {
            int tmp;
            string line = "";
            INISection section = null;
            try
            {
                fs = new FileStream(file, FileMode.OpenOrCreate);
                sr = new StreamReader(fs);
                line = sr.ReadLine();
                while (line != null)
                {
                    line = line.Trim();
                    if (line != "")
                    {
                        if (line.Substring(0, 1) == "[")
                        {
                            if (section != null) { sections.Add(section); }
                            tmp = line.IndexOf("]");
                            line = line.Substring(1, tmp - 1);
                            section = new INISection();
                            section.INISectionName = line;
                            line = sr.ReadLine();
                        }
                        else
                        {
                            if (line.Substring(0, 1) != ";")
                            {
                                tmp = line.IndexOf("=");
                                string name = line.Substring(0, tmp);
                                name = name.Trim();
                                section.INIParametr.Add(name);
                                string value = line.Substring(tmp + 1, line.Length - name.Length - 1);
                                value = value.Trim();
                                section.INIValue.Add(value);
                            }
                            line = sr.ReadLine();
                            if (line == null) { sections.Add(section); }
                        }
                    }
                    else
                    {
                        line = sr.ReadLine();
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
            finally
            {
                sr.Dispose();
                fs.Dispose();
            }
        }
        //********** ********** ********** ********** ********** ********** ********** ********** **********
    }
}


Пример использование:


GUIDE.CfgIni ini = new GUIDE.CfgIni(@"D:\Net\YYY\1.INI");
//если файл существует - открываем его для редактирования, если нет - создаем новый



//добавляем параметр и его значение в указанную секцию
ini.AddParametr("ODBC 32 bit Drivers", "yyy", "xxx");



//создаем новую секцию
ini.CreateSection("Sound");



//получаем значение указанного параметра в указанной секции
ini.GetIniData("Sound", "Baraban");



//изменяем значение
ini.UpdateValue("Sound", "Baraban", "100dB");


Есть и другие методы.
Много еще не сделано. Прошу Ваших комментарий.

Ошибка определения местоположения по базовым станциям или ошибка мобильного оператора?

Для своего мобильного приложения я использую определение местоположения по базовым станциям (библиотека cellid.dll, C#, Windows Mobile). Результаты определения местоположения попадают в базу на удаленном сервере. Вчера сделал возможность вывода координат на карты Google на своем сайте и вот что заметил:


А вот база данных:



Получается, что я менее чем за одно минуту из Новороссийска перебрался в Можайский район и обратно!

Хорошо если это ошибка в самой библиотеке (ранее не замечал), а если на самом деле телефон периодически посещает роуминг и совершенно по другой цене?

Есть ли мысли по этому поводу?

Обновление ПО на КПК через FTP

Я сделал таблицу в базе данных с одной записью. В ней храню: номер последней версии программы, размер cab-файла, контрольную сумму и путь к cab-файлу.
В программе на устройстве сделал кнопку «Check update». По нажатию на кнопку программа сверяет версию программы установленной и той что лежит на сервере, если они не совпадаю — программа скачивает удаленнй cab по ftp с проверкой размера и контрольной суммы. Теперь пользователь сам может установить обновление в любой точке земного шара. При выпуске новой версии не забудьте увеличивать счетчик версий или включите автомат. Проверить версию программы на устройстве можно так: System.Reflection.Assembly.GetExecutingAssembly().­GetName().Version.Major;

Загрузку осуществляю через ftp.
Вот пример ftp-клиента: FTPClient

Загрузка файла:
public bool GetFileFromServer(string localfn, string remotefn, string papka)
        {
            FtpClient ftp = new FtpClient(ftpServer, ftpUser, ftpPassword);
            try
            {
                ftp.Login();
                ftp.ChangeDir(@"Inbox");
                ftp.ChangeDir(papka);
                ftp.Download(remotefn, localfn, true);
            }
            catch (Exception e)
            {
                WriteLog("Address: GetFileFromServer. Message: " + e.Message + " Parameters: localfn = " + localfn +
                    ", remotefn = " + remotefn + ", papka = " + papka);
                return false;
            }
            finally
            {
                ftp.Close();
            }
            return true;
        }


Пример вызова:
if (!GetFileFromServer(localfn, remotefn, filename)) 
                                {
                                    WriteLog("Address: GetSendingsList. Message: " + " Unable to load file. Options: " + localfn + ", " + remotefn + ", " + filename);
                                    break; 
                                }


Сервер, пользователя и его пароль храню глобально. WriteLog — моя функция для ведения лога ошибок. Ftp в данном примере работает с докачкой.

Для верности я еще проверяю размер загруженного файла и контрольную сумму. Если надо приведу код проверки контрольной суммы. Пишите.

Работа с GPS на Windows Mobile

Была задача, написать приложение, которое с определенным интервалом времени получает координаты GPS приемника телефона и отправляет их в удаленную базу данных, а за тем выводит на Яндекс-карту. Долго искал каким способом это лучше осуществить и нашел его у себя на компьютере.

1. Открываем проект gps.sln (путь: c:\program files\windows mobile 6 sdk\samples\pocket pc\cs\gps);
2. Строим решение, получаем dll;
3. Подключаем полученую dll как ссылку к своему проекту;
4. Добавляем
using Microsoft.WindowsMobile.Samples.Location;


Объявляю глобальные переменные, что бы в них всегда хранились актуальные данные координат

double Latitude = 0;
        double Longitude = 0;


5. Инициализируем и включаем gps (я это делал в
Form.Load
):

updateDataHandler = new EventHandler(UpdateData);
                gps.DeviceStateChanged += new DeviceStateChangedEventHandler(gps_DeviceStateChanged);
                gps.LocationChanged += new LocationChangedEventHandler(gps_LocationChanged);
                if (!gps.Opened)
                {
                    gps.Open();
                }

6. Добавим функции:

void UpdateData(object sender, System.EventArgs args)
            {
                //получаем обновленные данные с GPS
                if (gps.Opened)
                {
                    if (device != null)
                    {
                        WriteLog(DateTime.Now.ToUniversalTime() + " Can not turn on your GPS device!");  
                    }

                    if (position != null)
                    {

                        if (position.LatitudeValid)
                        {
                            //выводим широту
                            Latitude = position.Latitude;
                        }

                        if (position.LongitudeValid)
                        {
                            //выводим долготу
                            Longitude = position.Longitude;
                        }
                    }
                }
            }

            void gps_DeviceStateChanged(object sender, DeviceStateChangedEventArgs args)
            {
                device = args.DeviceState;
                Invoke(updateDataHandler);
            }

            protected void gps_LocationChanged(object sender, LocationChangedEventArgs args)
            {
                position = args.Position;
                Invoke(updateDataHandler);

            }

Когда мне надо получить координаты я делаю так:

//работает ли GPS
                                    if (!position.LatitudeValid) 
                                    {
                                       //не работает
                                    }
else
{
 double lat = latitude;
 double lon = longitude;
}

Кординаты представленны как тип double, но можно представить как градусы, минуты и секунды для этого надо

position.Latitude
заменить на
position.LatitudeInDegreesMinutesSeconds;


Все отлично работает!

Не выводятся Exception - ы на Windows Mobile

Вы наверно часто сталкивались с таким сообщение:

Для этого исключения доступно сообщение об ошибке, но его невозможно отобразить, поскольку такие сообщения являются необязательными и в данный момент не установлены на этом устройстве. Установите «NETCFv35.Messages.EN.wm.cab» для Windows Mobile 5.0 и более поздних версий или «NETCFv35.Messages.EN.cab» для других платформ. Перезапустите приложение для отображения сообщения.

при разработке своих приложений. Вот решение как избавиться от данной проблемы:

1. Идете в C:\Program Files\Microsoft.NET\SDK\CompactFramework\v3.5\Wind­owsCE\Diagnostics;
2. Распаковываем файл NETCFv35.Messages.EN.wm.cab, который там лежит;
3. Ищем в распакаваных файлах — SYCCFA~1.001;
4. Переименовываем его в System.SR.dll;
5. Добавляем этот получившийся файл как ссылку к проекту в Visual Studio.

Все. Теперь Exception — ы выводятся.