Работа мобильных устройств с навигационной системой внутри помещений
Реализация программного решения по из взаимодействию друг с другом клиент-серверного приложения и web-сервера. Обеспечение мобильного устройства пользователя данными, необходимыми для навигации. Внесение корректив в таблицы с датчиками и картами.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | курсовая работа |
Язык | русский |
Дата добавления | 23.08.2017 |
Размер файла | 766,6 K |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
Размещено на http://www.allbest.ru/
Размещено на http://www.allbest.ru/
Оглавление
Обозначения и сокращения
Введение
Обзор используемых технологий
Постановка задачи и требований к системе
Обзор существующих решений
Проектирование и разработка
Предоставление данных
Проектирование web-компонентов
Проектирование графического интерфейса
Проектирование базы данных
Аутентификация
Регистрация
Взаимодействие с MSSQL Server
Заключение
Список изученной литературы
Приложения
Обозначения и сокращения
ORM (Объектно-реляционное отображение) - технология, объединяющая базы данных с использованием объектно-ориентированных языков посредством создания в них «виртуальной объектной базы данных».
БД- база данных.
IDE (Интегрированная среда разработки) - набор программных средств, позволяющий создавать программное обеспечение на базе данного продукта.
CLR (Общеязыковая исполняющая среда) - байт-кодовая исполняющая среда, в который компилируются программы, написанные на основе.NET.
.Net- framework, являющийся программной платформой, основанной на CLR.
ASP (Active Server Pages) - технология, основанная на реализации динамических web-страниц на стороне сервера.
Клиент - сторона, инициирующая взаимодействие и посылающая запрос в клиент-серверной архитектуре.
Сервер - сторона в клиент-серверной архитектуре, которая, при получении запроса выполняет определенные действия, результат которых отправляет обратно в виде сообщения.
HTTP (HyperText Transfer Protocol) - протокол прикладного уровня передачи данных, основанный на технологии «клиент-сервер». Его работа происходит по принципу «запрос-ответ». Его основным объектом является ресурс, на который указывает унифицированный идентификатор ресурса в запросе. В простейшем случае используются методы GET и POSTдля загрузки данных и их отправки, соответственно.
BLE (Bluetooth low energy) - беспроводная Bluetooth-технология с низким потреблением энергии.
SQL (Язык структурированных запросов) - язык, который используется в реляционных базах данных, управляемых соответственными системами управления базами данных, для работы с данными.
LINQ (Language Integrated Query) - разработанный для.Net технологии язык запросов, напоминающий SQL. К особенностям данного SQL-подобного языка, относятся анонимная типизация, методы расширения, лямбда-исчисление, дерево выражений.
API (Программный интерфейс приложения) - набор классов, процедур, функций, и.т.д., который предоставляется программным продуктом для использования во внешних продуктах. Чаще всего используется для написания приложений.
OWIN (The Open Web Interface for.NET) - спецификация, определяющая взаимодействие веб-сервера с веб-приложением.
Unicode - стандарт для кодирования символов.
Smtp-сервер - сервер, с которого происходит отправление послания адресату. Чаще всего используется в веб-приложениях для подтверждения регистрации пользователя и отправки информационных рассылок и уведомлений на адреса пользователей.
Тайлы- небольшие фрагменты одинакового размера, являющиеся частями одного изображения.
Введение
В век высоких технологий у людей все чаще возникает интерес к навигации внутри зданий, на что, помимо величины современных построек, так же влияет и рост возможностей, например, по использованию услуг, привязанных к конкретным координатам внутри здания. У пользователей навигационных приложений появляется возможность всегда быть в курсе событий, окружающих их.
Стоит отметить, что для того, чтобы определить свое местоположение внутри помещения, пользователь не нуждается в каких-то специфических приборах и инструментах, в наше время навигация осуществляется при помощи мобильных устройств, в которых имеется технология BLE и установлено специальное навигационное приложение. Для его нормального функционирования, в здании, в котором будет осуществляться навигация, так же должны быть размещены датчики, оснащенные BLE технологией (называемые биконами), которые передают мобильному устройству сигнал по широковещательной рассылке и дают приложению возможность оценить по нему местоположение устройства и, соответственно, пользователя. Вся информация о датчиках и их местоположении хранится в базе данных, откуда она, по запросу, посредством специальных сервисов, передается на мобильное устройство пользователя и используется в навигационных целях.
В данной работе было реализовано программное решение, состоящее из взаимодействующих друг с другом клиент-серверного приложения и web-сервера, взаимодействующих друг с другом через базу данных, основная задача которых состоит в том, чтобы обеспечить мобильное устройство пользователя данными, необходимыми для навигации, а также вносить коррективы в таблицы с датчиками и картами. Впоследствии эти данные будут использоваться мобильным навигационным приложением.
Обзор используемых технологий
мобильный навигация серверный
При разработке решения были использованы следующие технологии и программное обеспечение:
Visual Studio - VS была выбрана в качестве среды разработки. VS является официальной IDE для разработки программного обеспечения, в том числе и веб-приложений. Включает в себя редактор исходного кода, встроенный отладчик и множество дополнительных встраиваемых инструментов.
ASP.NET - технология, которая предназначена для создания веб-приложений и сервисов. Является продуктом объединения двух старых технологий.NET и ASP, но базируется на CLR и включает в себя новые преимущества перед предыдущими технологиями, такие как усовершенствованный механизм обработки ошибок, пользовательские элементы управления, возможность кэширования данных
Платформа ASP.NET MVC- framework для разработки сайтов и веб-приложений на основе Model-View-Controller шаблона. Данный архитектурный шаблон позволяет разделить данные приложения, его пользовательский интерфейс и управляющую логику на три независимых компонента. Модели (Models) реализуют логику для домена данных веб-приложения. Представления (Views) отображают пользовательский интерфейс. Контроллеры (Controllers) обеспечивают взаимодействие приложения с пользователем, работают с данными модели и выбирают подходящие представления.
ASP.NET Web API- framework, позволяющий легко создавать HTTP сервисы.
ASP.NET Identity - система добавления в решение функционала для авторизации, доступная для внедрения в любой ASP.NET проект.
Microsoft SQL Server-система управления реляционными базами данных, основным языком запросов в которой является Transact-SQL.
ADO.NET Entity Framework - технология, созданная в рамках объектно-ориентированного подхода, являющееся ORM решением для.NET Framework. Обеспечивает возможность обращения к таблицам базы данных через классы C#. В Entity Framework работа с SQL-запросами была заменена на более простую работу с LINQ.
Leaflet --открытая JavaScript библиотека, предназначенная для создания и работы с картами на веб-сайтах.
Git -система контроля версий исходного кода.
С# - объектно-ориентированный язык программирования, первоначально предложенный разработки приложений на основе.NET платформы.
HTML- язык разметки документов, используемых в Интернет.
CSS- язык стилей, задающий внешний вид документов, написанных с помощью языков разметки, например, HTML.
JavaScript - встраиваемый язык программирования, используемый для создания интерактивных web-страниц.
Постановка задачи и требований к системе
Основной целью данной работы было поставлено обеспечение мобильных устройств данными, необходимыми для работы навигационной системы внутри помещений. В связи с этим работа была разделена на три основные задачи:
Первая часть включала в себя проектирование и создание базы данных, в которой должны были храниться все данные, необходимые для корректного использования навигационных приложений.
Вторая часть включала в себя клиент-серверное web-приложение, в котором необходимо было реализовать сервисы, позволяющие создавать, заполнять и редактировать данные таблиц в базе данных. Данные сервисы должны были быть реализованы в виде web-страниц редактирования карты (с формами добавления новых узлов и биконов на карту, а также редактирования уже имеющихся), формы загрузки карт для ее дальнейшего разбиения на тайлы, необходимого для создания масштабируемых карт, страницы с таблицами зданий, карт, узлов и биконов. Интерактивные карты должны быть интегрированы при помощи Javascript библиотеки Leaflet.
Последняя часть включала в себя web-сервер, направленный на использование данных из уже заполненной базы данных. Использование сервера должно проходить таким образом- сторонними мобильными приложениями запрашивается информация о полях таблицы, и если запрос содержит в себе все данные, необходимые для его выполнения, то ему выдается ответ. Также необходимо было определить, в каком формате должны передаваться данные.
Обзор существующих решений
В настоящее время, с ростом размеров современных зданий, возрастает и потребность в навигации внутри них. К сожалению, повсеместно используемые методы спутниковой навигации, применяемые в системах позиционирования вне зданий, не могут использоваться в плотно застроенной местности, в том числе и в помещениях. На данный момент, помимо спутниковой навигации, существует немало методов определения местоположения пользователя, многие из которых используются и для indoor-навигации:
Одним из существующих методов является навигация по Wi-Fi, для реализации которой необходимо обеспечить достаточно надежную сеть с беспроводными точками доступа. Он не очень удобен в использовании, так как для достаточной точности такого метода навигации необходимо обеспечить отсутствие вмешательств в работу роутеров, их бесперебойную работу и неизменное местоположение. При несоблюдении данных условий погрешность в определении местоположения может увеличиваться более, чем в 6 раз, что и является основной проблемой данного метода.
Метод ориентирования по станциям операторов сотовой связи, по большей мере, не сильно отличается от навигации по Wi-Fi, так как для его работы так же необходимо сохранять в базе данных координаты местонахождения каждой станции, которые позже используются для вычисления местоположения мобильного устройства. Для этого необходимо определить, какие станции находятся в зоне видимости мобильного устройства в данный момент времени, и отправить эти данные на один из специализированных открытых сервисов, который вышлет в ответ данные с координатами данных станций. Остается только использовать эти данные для определения своего местоположения методом триангуляции. Стоит отметить, что данный метод имеет еще большую погрешность, чем приведенный ранее.
Геомагнитная навигация тоже имеет малую точность определения местоположения пользователя, и причиной тому служит нестабильность магнитных аномалий в помещениях, которая усиливается бытовыми электроприборами. А также данный метод требует для своей работы специализированных устройств, оснащенных магнетометром. Их работа происходит следующим образом- магнитометр изменяет геомагнитные аномалии на определенной территории, они наносятся на карту данной местности, и далее, используя эту карту, мобильное устройство находит, где находится пользователь в данный момент времени.
Позиционирование при помощи BLE-маячков (так же называемых beacon). Данный метод, по причине его достаточно высокой точности и экономного использования, и был использован в данном проекте. Этот метод основан на приеме мобильным устройством радиосигналов от BLE-датчиков, размещенных в определенных точках внутри зданий. Каждый датчик с определенной периодичностью транслирует информацию, однозначно его идентифицирующую. Приложение в телефоне пользователя, получившее эти данные от датчиков, в радиусе действия которых пользователь находится, сверяет полученную информацию с базой данных, извлекает из нее координаты нахождения датчиков, и на основе силы принятого сигнала определяет местоположение пользователя. У данного метода так же есть недостатки, к которым мы можем отнести малый срок службы современных датчиков (до трех лет) и незащищенность системы от вмешательства извне (действительно, информация об одном из датчиков (ее вид будет рассмотрен ниже) может быть продублирована в «поддельный beacon» (его роль может сыграть любой микроконтроллер, имеющий специальную прошивку и BLE-чип) и будет создавать помехи в работе системы, при помещении подделки в часть здания, отличную от места размещения оригинального датчика).
Стандартный BLE-датчик в равные промежутки времени транслирует информацию о себе, содержащую: префикс пакета (преамбулу), обозначающий, что сигнал исходит именно от beacon, 128 битный идентификатор группы маяков (proximity UUID), который по определенным признакам объединяет группу зданий, в которых размещаются датчики с таким идентификатором группы (например, здания, принадлежащие одной организации, или находящиеся в одном районе),
16 битный мажор, по определенному принципу объединяющий подгруппу в группе маяков с одинаковым идентификатором группы (например, один мажор может быть у группы маяков, находящихся в одном здании),
16 битный минор, идентифицирующий каждый отдельный датчик внутри общего мажора, 8 битное эталонное значение мощности маяка, представляющее собой силу сигнала датчика, измеренную на расстоянии 1м от него, данное значение и используется для определения расстояния между приемником сигнала (в нашем случае, мобильным устройством) и датчиком, транслирующим сигнал. Для этого на стороне пользователя вычисляется реальное RSSI- значение, характеризующее силу принятого мобильным устройством сигнала и сравнивается с эталонным значением Measured Power. Чем больше данное значение, тем ближе к испускающему его датчику находится принимающая сторона.
Как было сказано выше, мобильное устройство, при попадании в область действия маяков, измеряет их значения и определяет по ним свое местоположение. На данный момент существуют наиболее популярными считаются два способа определения местоположения- трилатерация, которая определяет местоположение объекта путем построения смежных треугольников на области определения координат, и последующим расчетом длин их сторон, и «метод отпечатков», который и был выбран для работы мобильного приложения. Данный метод характеризуется тем, что сперва в некотором множестве точек данной местности измеряются значения векторов RSSI, которые сохраняются вместе с точками, в которых были измерены. Тогда местоположение пользователя определяется при помощи сравнения полученных пользователем RSSI значений с значениями, полученными ранее.
Проектирование и разработка
Посредством представленных ранее технологий необходимо было осуществить взаимодействие программного решения с пользователями и с мобильным приложением. C использованием технологий ASP.NET Web API и Entity Framework представилось возможным создание удобного сервера с сервисами, отправляющими на мобильное устройства запрашиваемые данные, которые необходимо было получать из БД. Для этого сперва необходимо было спроектировать базу данных, для чего была предложена СУБД Microsoft SQL Server. После проектирования и создания базы данных, ее необходимо было заполнить информацией, необходимой для навигации - данными о датчиках, картах, зданиях. Чтобы работа с данными осуществлялась быстрее и проще, было решено создать web-приложение с удобными формами редактирования данных- в виде таблиц и в виде карт. Для этого были предложены к использованию технологии ASP.NET MVC и Entity Framework. Для удобной работы с картами зданий также была предложена Leaflet- библиотека. Рассмотрим подробнее, как осуществлялись предложенные решения:
Предоставление данных
Исходя из поставленной задачи, web-приложение должно отдавать данные, необходимые для реализации навигации на мобильном устройстве пользователя. К таким данным относятся:
Данные о пользователях
Данные о картах
Данные о зданиях
Данные об узлах и датчиках
Всего было рассмотрено два варианта передачи данных, каждый из которых решено было использовать в системе. Первый вариант предназначался для не текстовых данных - изображений, которые будут передаваться в соответствующем формате и сохраняться на устройстве пользователя. Таким образом, пользователь будет иметь возможность использовать систему навигации даже при отсутствии подключения к интернету. Второй вариант будет применяться для всех остальных данных- для них был выбран формат JSON.
JSON является одним из самых удобных текстовых форматов, используемых для обмена данными. Основное достоинство данного формата заключается в том, что текст сообщения может быть написан и прочитан как человеком, так и компьютером. Данный формат выглядит следующим образом:
либо это набор пар «ключ-значение», где ключом может являться только строка, а значением любая форма. В разных языках такая структура находит применение как объект, список, словарь.
либо это упорядоченный набор значений, реализуемый, например, как массив или последовательность.
Значения могут принимать любой вид из представленных ниже:
Объекты - объектом называется такое множество пар «ключ-значение», которое заключается в фигурные скобки, и в котором каждый ключ описывается строкой и сопровождается двоеточием, отделяющим его от значения. Пары отделяются друг от друга запятыми.
Массивы - упорядоченная (в отличие от объектов) коллекция значений, которая заключается в квадратные скобки, и внутри которой все значения отделяются друг от друга запятыми.
Числа.
Строки - упорядоченная коллекция символов Unicode (допустимы и нулевые строки, включающие в себя 0 символов), которая заключается в двойные кавычки. В строке могут использоваться управляющие последовательности, в таком случае в начале каждой из них должна стоять символ «\».
Литералы - true/false/null
Чтобы осуществлять автоматическую передачу данных в формате JSON, необходимо изменить настройки Web API конфигуратора. По умолчанию, данная технология поддерживает как XML формат, так и JSON. Но так как в данной работе основная масса данных возвращается сервисами именно в виде JSON, оптимальным решением будет установить его форматом по умолчанию. Для этого следует добавить в конфигуратор такую конструкцию: config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
После этого, когда пользователь будет обращаться к HTML тексту (то есть указывать его в accept заголовке запроса), то самый высокий приоритет ответа будет именно у формата JSON, следовательно, ответ будет получен именно в таком виде. Но если пользователь будет запрашивать именно XML, тогда ответ будет получен в данном формате, так как он все равно продолжает поддерживаться приложением.
Проектирование web-компонентов
Согласно требований системы, web-приложение представляет из себя средство для работы администратора с данными в таблицах и на картах, а web-сервер включает в себя сервисы, к которым могут обращаться мобильные устройства, и приложение. Между собой они связаны базой данных, в которой хранятся все навигационные данные, и к которой каждая из них обращается.
Web-приложение
Web-приложение включает в себя данные страницы:
Начальная страница- она же страница регистрации.
Страница редактирования карт- страница, на которой администратору доступны функции создания узлов и биконов и их редактирования.
Страницы биконов, узлов, зданий, этажей - страницы, содержащие в себе соответственно таблицы датчиков, узлов, зданий и этажей, доступные для заполнения и редактирования их полей.
Страница пользователей - таблица, содержащая в себе информацию о пользователях, имеющая функции редактирования и добавления.
Страница создания карт - страница, предоставляющая пользователю возможность выбрать для загрузки файл с изображением карты. После загрузки будет происходить разбиение карты на тайлы и сохранение их в соответствующую иерархию папок.
Страница создания карт представляет из себя форму загрузки изображения с картой этажа. При загрузке карты она сохраняется на сервер в папку с порядковым идентификатором. В ту же папку сохраняется иерархия папок, с созданными разномасштабными тайлами данного изображения. В дальнейшем они будут использоваться для создания интерактивных масштабируемых карт. Количество корневых каталогов с тайлами соответствует количеству уровней зума у карты. Разбиение на тайлы происходит таким образом:
Сперва необходимо определить максимальный зум, допустимый для нашего изображения (то есть минимально допустимое отдаление, при котором вся картинка помещается в один тайл заданного размера)- отметим, что в случае, когда максимальный уровень зума равен, например, 3, то количество иерархий папок будет равно 4 (так как нумерация папок начинается с 0).
Запускаем цикл разбиения на тайлы.
Разбиение на тайлы начинается с самого максимального зума (в данном случае 3), после чего исходное изображение уменьшается в два раза и происходит следующий проход по циклу разбиения.
Для корректной работы алгоритма нарезки на тайлы выбранное изображение приводится к виду, в котором его ширина и высота кратны заданным размерам тайла (то есть производится округление в большую сторону относительно размеров тайла).
Для изображения в выбранном масштабе получаем графический буфер, длина которого равна относительной длине картинки, умноженной на заданный размер тайла. Ширина рассчитывается таким же образом. Далее изображение копируется в графический буфер, заполняя предоставленную область начиная с верхнего левого угла. Незаполненные области остаются белыми.
Далее запускается цикл по рассчитанной относительной ширине и длине соответственно.
В цикле создается тайл и в него копируются данные из графического буфера в соответствии с текущими значениями итераторов цикла.
В цикле - после создания, тайл сохраняется по необходимому для корректной работы внешней библиотеки Leaflet пути - "выбранная папка сохранения\\зум\\координата по оси х в относительных значениях\\координата по оси у в относительных величинах.пнг".
Далее осуществляется переход к следующей итерации цикла.
После завершения алгоритма разбиения администратор добавляет путь к папке с картой в соответствующее поле базы данных. При обращении к этому полю через страницы редактора карт и просмотра карт подключенная к проекту библиотека Leaflet «собирает» из подготовленных нами тайлов карту. При обращении карта собирается из той папки, значение которой равно уровню зума, установленного нами по умолчанию. При изменении зума- увеличении, например- происходит переход к папке в данном каталоге, у которой меньший порядковый номер (если она существует). При уменьшении, соответственно, номер становится больше.
Приложение имеет такую структуру:
Рис.1. Диаграмма классов
Классы DbContext, IdentityUser, IdentityDbContex, HttpApplication, SigninManager, Controller являются базовыми, от которых соответственно наследуются класс контекста базы данных DB_9DE66D_beacons, класс ApplicationUser, представляющий данные о пользователях, класс контекста данных ApplicationDbContext, используемый в системе ASP.NET Identity, класс с функционалом инициализации приложения MvcApplication, классы ApplicationSigninManager и ManageController, содержащие функционал для регистрации пользователей, класс системы авторизации AccountController и класс контроллеров с функционалом для карт и таблиц по работе с навигационными данными.
Web-сервер
Сервер имеет такую структуру:
Рис.2. Диаграмма классов
Где ApiController и Controller являются базовыми классами, от которых наследуются все остальные классы. AccountController является классом, содержащим функционал для авторизации и аутентификации пользователей. Классы IbeaconController, NodeController, MapController, BuildController представляют функционал для работы с датчиками, узлами, картами и зданиями соответственно. Класс, в который был вынесен весь смежный функционал по данным из БД, называется HomeController.
Web-сервер предназначен для работы мобильного приложения с сервисами. К таким сервисам относятся сервисы, отдающие данные о картах, зданиях, узлах и биконах. В данной работе были реализованы сервисы для получения:
информации о биконах (GetIBeacons)
информации о биконе по id бикона (GetIBeaconById)
информации о биконах по uuid, minor, major бикона (GetIBeaconByUuidMinorMajor)
информации о биконах по id здания (GetIBeaconsByBuildingId)
информации о биконах по id карты (GetIBeaconsByMapId)
количества биконов (GetIBeaconCount)
количества биконов на этаже (GetIBeaconCountByMap)
информации о биконах без заряда батареи и идентификатора карты (GetBeaconWithEventWithOutBatLvlAndMapId)
информации о зданиях (GetBuildings)
информации о здании по id (GetBuildingsById)
названий зданий (GetBuildingNames)
матриц смежности по id здания в виде JSON-строки по зданию (GetMatrix)
id здания по id бикона (GetBuildingIdByBeaconId)
информации об этажах (GetMaps)
информации об этажах по id (GetMapInfoByMapId)
пути к карте по id (GetMapPathByID)
id этажа по id здания (GetMapIdByBuilding)
пути к карте по id бикона (GetMapPathByBeaconId)
id этажа по id бикона (GetMapIdByBeacon)
информации об узлах (GetNodes)
информации об узлах по id (GetNodeById)
информации об узлах по id здания (GetNodesByBuildingId)
информации об узлах по id здания (GetIBeaconsByMapId)
Кроме того, в процессе выполнения работы были созданы сервисы для записи в БД информацию о состоянии батареи датчика, создания и удаления узлов и биконов, отправки карт и изображений, а также сохранения матрицы, полученной из редактора карт, в файл.
Рассмотрим работу с сервисами на примере сервиса для получения id карты по идентификатору здания.
Рис.3. Сервис для получения идентификатора карты по id здания
Клиент посылает запрос по маршруту api/Map/getMapIdByBuildingId/1 с идентификатором карты 1. Если в запросе присутствуют все необходимые параметры, тогда происходит обращение к классу new_floors из которого отбираются все строки карт с таким внешним ключом, и клиенту отдается содержимое графы floorId каждой такой строки, в которую и записаны идентификаторы данного этажа. Вид возвращаемого JSON - [{"floorId":1},{"floorId":3},{"floorId":4},{"floorId":5},{"floorId":6},{"floorId":7}]
Следующий пример представляет сервис для получения данных об узлах по идентификатору здания.
Рис.4. Сервис для получения информации об узлах, находящихся в здании
В данном примере происходит обращение к классу new_floors из которого отбираются все строки карт с соответствующим идентификатором здания. Далее отбираются такие узлы, чьи внешние ключи, связанные с картами, совпадают с идентификаторами отобранных полей таблицы карт, после чего подготавливаются данные, отправляемые пользователю на мобильное устройство. Ответ имеет вид:
[{"NodeId":1,"IbeaconIdFk":1,"mapIdFk":1,"coordX":-
176,"coordY":203,"nodeNum":1,"type":null},{"NodeId":2,"IbeaconIdFk":
2,"mapI dFk":1,"coordX":-
150,"coordY":100,"nodeNum":1,"type":null},{"NodeId":
3,"IbeaconIdFk":1,"mapIdFk":1,"coordX":-
130,"coordY":70,"nodeNum":1,"type":null}].
По данным схемам происходит взаимодействие и большинства остальных сервисов с приложениями.
Проектирование графического интерфейса
Прежде, чем конечный пользователь получит данные на свое мобильное устройство, данные необходимо записать в базу данных. Для простого выполнения этой задачи администратором, был создан интуитивно понятный графический интерфейс web-приложения для записи данных. Согласно шаблону MVC, всю работу по генерированию элементов пользовательского интерфейса, управлению разметкой и вставке в нее кода выполняет представление. Движком представления, применяющимся в данной работе, является Razor. Работает он таким образом- так как файлы представления не являются статическими HTML страницами, то в процессе генерации ответов контроллера с использованием представлений генерируется страница HTML.
Проектирование базы данных
База данных включает в себя таблицы зданий, этажей, датчиков и узлов.
Рис.5. Таблицы данных
Кроме того, у клиент-серверного приложения и у web-сервера имеется свои таблицы с зарегистрированными пользователями. Web-приложения имеют собственные сущности, дублирующие таблицы базы данных. Это сделано для того, чтобы, поскольку приложение отвечает, в основном, за работу с пользователями, оно обеспечивало ему возможность создания и редактирования полей в базе данных, а также создание, просмотр и редактирование уже имеющихся интерактивных карт.
Аутентификация
Чтобы воспользоваться web-сервисами, предоставляющими мобильным устройствам данные, необходимо пройти регистрацию и аутентификацию. Всего на базе Web API существуют три типа аутентификации- через куки, через внешние сервисы и аутентификация при помощи токена. В данной работе был реализован последний тип. В Web API имеются специальные компоненты OWIN, участвующие в генерации токенов, и их дальнейшей проверке. Аутентификация с использованием этих компонентов проходит таким образом:
Сперва пользователю необходимо получить токен, для этого он вводит свои данные, полученные при авторизации (логин и пароль), после чего клиент отправляет данные серверу авторизации и запрашивает токен у ресурса /Token.
Если в обращении содержится пара «заголовок «grand_type»-значение «password»», то происходит вызов метода GrantResourceOwnerCredentials() провайдера авторизации ApplicationOAuthProvider, который используется для генерации токена.
После успешной генерации, данный провайдер запрашивает валидацию данных отправленных пользователем - логина и пароля- у класса ApplicationUserManager, использующегося для управления пользователями.
В случае успешного прохождения валидации провайдер авторизации генерирует и возвращает пользователю токен, открывающий доступ к ресурсам web-сервисов.
Чтобы воспользоваться этими ресурсами, необходимо, чтобы каждый следующий запрос клиента включал в себя полученный токен. Как видно на изображении ниже, при обращении клиента к фильтру авторизации, фильтр авторизации запрашивает валидацию токена у компонент OWIN.
При успешном прохождении валидации токена, происходит проверка прав доступа пользователя, производимая фильтром авторизации.
Если пользователь имеет необходимые для доступа к ресурсу права, то ApiController отдает пользователю запрашиваемые ресурсы, в ином же случае пользователь получает код ошибки 401(Unauthorized).
Рис.6. Диаграмма взаимодействия
Регистрация
Чтобы иметь возможность работать с таблицами приложения, а также иметь доступ к созданию и редактированию карт, администратору необходимо пройти регистрацию с требуемыми правами. Пользователь, не имеющий требуемых прав, также может просматривать таблицы и карты, но, чтобы иметь возможность изменять данные в них, необходимо пройти регистрацию со статусом администратора. Для регистрации пользователю необходимо создать новую учетную запись и пройти подтверждение по электронной почте, имеющей формат «name@hse.ru». После этого, при входе в свою учетную запись, пользователь получит доступ к таблицам и картам.
Рассмотрим, как реализуется регистрация с подтверждением по электронной почте с использованием технологии ASP.NET Identity. Для нашего web-приложения был выбран тип аутентификации вида «Individual User Accounts», так как он имеет множество инструментов, позволяющих реализовать авторизацию не только через форму регистрации внутри приложения, но и регистрацию пользователей через сторонние сервисы (например, социальные сети), при условии наличия у пользователя аккаунтов в данных системах. При таком типе аутентификации во процессе регистрации первого пользователя создается база данных, включающая в себя таблицы, содержащие:
Логины пользователей (AspNetUserLogins)
Данные зарегистрированного пользователя (AspNetUsers)
Определения возможных ролей для пользователей (AspNetRoles)
Связи, присваивающие роли определенным пользователям (AspNetUserRoles)
Весь функционал по работе с пользователями приложения и ролями содержится в базовых классах UserManager и RoleManager соответственно.
Выше было введено новое понятие «роли». Роли в ASP.NET Identity дают разработчику возможность разграничивать доступ для различных групп пользователей, имеющих соответствующие права. Это значит, что в зависимости от имеющихся у него прав, пользователь будет иметь или не иметь доступ к определенным ресурсам приложения. Чтобы задействовать систему ролей в приложении, в нашем приложении был использован подобный алгоритм:
Сперва необходимо проинициализировать БД с первоначальными значениями ролей и пользователей. Чаще всего применяются две роли- администратор и пользователь.
В базу данных добавляются пользователи, имеющие роль «администратор». При создании объектов классов RoleManager и UserManager указывается определенный по умолчанию контекст данных для работы с пользователями и их ролями. Соответствующие им методы roleManager.Create и userManager.AddToRole добавляют новую роль в таблицу AspNetRoles и сохраняют связь между идентификатором пользователя и данной ролью в таблицу AspNetUserRoles.
Следующим шагом устанавливаются методы присвоения ролей только зарегистрированным пользователям. В нашем случае, при регистрации всем пользователям присваивалась роль «пользователь»
Далее у всех методов, которые должны быть недоступными пользователю, не имеющему права администратора, устанавливаются ограничения доступа посредством добавления атрибута [Authorize(Roles="admin")]. Если в приложении имеются методы, которые должны быть доступны только зарегистрированным пользователям, то в них используется атрибут [Authorize].
Рис.7. Формы регистрации
Как видно на изображениях выше, при регистрации также необходимо пройти подтверждение по электронной почте. Для этого уникальный токен, сгенерированный при помощи базового метода UserManager.GenerateEmailConfirmationTokenAsync, используется для формирования ссылки «подтверждения регистрации», которая отправляется на почту пользователя, указанную им при регистрации. Отправка производится с использованием функционала метода UserManager.SendEmailAsync, а вся информация о логине, пароле отправителя, а также адрес и порт smtp-сервера, с которого будет производиться отправление письма, сохраняется в базовом классе EmailService.
После того, как пользователь получает письмо со ссылкой на метод Login и переходит по ней, происходит обновление данных данного пользователя в БД, где полю подтверждения регистрации EmailConfirmed присваивается истинное значение, и регистрация считается законченной. Пользователю становятся доступны запрашиваемые ресурсы, соответствующие его правам.
Взаимодействие с MSSQL Server
Оба web-компонента взаимодействует с базой данных, размещенной на сервере, посредством Entity Framework. В приложениях были сгенерированы классы, дублирующие сущности описанной выше базы данных. С их помощью происходит все взаимодействие с бд- создание и запись новых элементов, а также редактирование и удаление старых. Ниже представлен метод контроллера этажей для представления информации об этажах:
Рис.8. Форма просмотра этажей
Ниже представлено окно редактирования этажа.
Рис.9. Форма редактирования этажей
И окно работы с картами.
Рис.10. Форма редактирования карт
Рассмотрим, каким образом Entity Framework был использован для генерации кода доступа к данным БД. В нашем случае был использован подход Database-First, который был самым первым подходом, предложенным данной технологией, и к которому прибегают тогда, когда у разработчика уже имеется в наличии существующая и работающая база данных.
Первым делом в MS SQL Server создается база данных, на основе которой будет создана графическая модель.
Далее в наш проект необходимо добавить новый объект библиотеки классов и добавить в него новый элемент на базе шаблона ADO NET Entity Data Model.
Следом за этим в окне Entity Data Model Wizard выбирается подход для работы с Entity Framework- в нашем случае, как было сказано выше, это подход DB-first.
Далее настраивается подключение к MS SQL Server, и Visual Studio предлагает выбрать те элементы базы данных, которые вы хотели добавить в свое приложение.
Далее Visual Studio извлекает из БД всю выбранную пользователем информацию и генерирует класс контекста для доступа к БД.
Заключение
Цель данной работы состояла в создании программного решения, при помощи которого осуществляется навигация внутри зданий. В рамках данной работы были разработаны web-компоненты, которые обеспечивают правильное функционирование мобильного приложения для навигации, а также создают удобную систему для генерации данных и взаимодействия с ними.
В ходе проектирования были изучены существующие решения и был произведен поиск оптимального решения поставленной задачи. В ходе данной работы были изучены следующие технологии и инструменты:
ASP.NET MVC, ASP.NET Web API, Entity Framework, Leaflet, Visual Studio, MSSQL Server, языки C#, HTML, JavaScript, CSS.
При помощи вышеупомянутых технологий было реализовано программное решение в виде совокупности web-компонентов на основе технологий ASP.NET, в которой был разработан весь требуемый функционал- была спроектирована база данных, архитектура и логика двух web-компонентов, был проработан графический интерфейс.
Список изученной литературы
[1] Lakshmiraghavan, Badrinarayanan. Pro ASP.NET Web API Security, 2013.
[2] Изучаем ASP.NET MVC 5. URL: https://professorweb.ru/my/ASP_NET/mvc/level1/, (дата обращения 10.02.2017)
[3] Uurlu Ali, Zeitler Alexander, Kheyrollahi Ali. Pro HTTP Web Services in ASP.NET, 2013.
[4] Подтверждение Email в ASP.NET Identity 2.0 URL: https://metanit.com/sharp/mvc5/12.8.php, (дата обращения 15.03.2017)
[5] Авторизация и аутентификация в MVC 5, ASP.NET Identity. URL: https://metanit.com/sharp/mvc5/12.1.php, (дата обращения 01.04.2017)
[6] Leaflet API Reference. URL: http://leafletjs.com/reference-1.0.3.html, (дата обращения 01.04.2017)
Приложение 1
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using App_HSE.Models;
namespace App_HSE.Controllers
{
public class CreateTilesController: Controller
{
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(IEnumerable<HttpPostedFileBase> fileUpload)
{
//string path = "C:\\Users\\Екатерина\\Desktop\\strogino\\strogino\\files";
//string path1 = "C:\\Users\\Екатерина\\Desktop\\strogino\\strogino";
string path = null;
string src_path = null;
foreach (var file in fileUpload)
{
if (file == null) continue;
path= AppDomain.CurrentDomain.BaseDirectory; //+ "UploadedFiles\\";
src_path = Path.GetFileName(file.FileName);
if (src_path!= null) file.SaveAs(Path.Combine(path, src_path));
src_path = Path.Combine(path, src_path);
//if (src_path!= null) src_path = Path.Combine(path, src_path);
}
var img_src = Image.FromFile(src_path);
int map_def_size = 256;
int zoom = (int)Math.Ceiling((Math.Log(Math.Max(img_src.Height, img_src.Width) / map_def_size, 2)));
int map_w = ((int)Math.Ceiling((double)img_src.Width / map_def_size)) * map_def_size;
int map_h = ((int)Math.Ceiling((double)img_src.Height / map_def_size)) * map_def_size;
/*
* 1 - вычисляем начальные размеры исходя из размера окна отображения
* 2 - для заданного числа зумов делаем папки с нарезками, при этом каждая папка это увеличение начальных размеров на 2
* 1 - делаем большую картинку
* 2 - вычисляем количество столбцов и строк с округлением в большую сторону
* 3 - режем картинку по столбцам и строкам
*
* Профит!!!
*/
for (int z = zoom; z > 0; z--)
{
var tmp_w = map_w;
var tmp_h = map_h;
var tmp_columns = (int)Math.Ceiling((double)tmp_w / map_def_size);
var tmp_rows = (int)Math.Ceiling((double)tmp_h / map_def_size);
var img = ScaleImage(img_src, tmp_columns, tmp_rows, tmp_w, tmp_h);
var tiler = new ImageTile(img, tmp_columns, tmp_rows, z - 1);
tiler.GenerateTiles(path);
map_w /= 2;
map_h /= 2;
}
return RedirectToAction("Index");
}
static Image ScaleImage(Image img, int nWidth, int nHeight, int imgWidth, int imgHeight)
{
int w = 256 * nWidth;
int h = 256 * nHeight;
int x = 0;
int y = 0;
Image dest = new Bitmap(w, h);
Graphics gr = Graphics.FromImage(dest);
gr.DrawImage(img, x, y, imgWidth, imgHeight);
return dest;
}
public class ImageTile
{
private Image image;
private Size size;
private int zoom;
public ImageTile(Image inputFile, int xSize, int ySize, int Zoom)
{
image = inputFile;
size = new Size(xSize, ySize);
zoom = Zoom;
}
public void GenerateTiles(string outputPath)
{
int xMax = image.Width;
int yMax = image.Height;
int tile = 256;
for (int x = 0; x < size.Width; x++)
{
DirectoryInfo di = Directory.CreateDirectory(string.Format("{2}\\m{0}\\m{1}", zoom, x, outputPath));
for (int y = 0; y < size.Height; y++)
{
string outputFileName = Path.Combine(string.Format("{2}\\m{0}\\m{1}", zoom, x, outputPath), string.Format("{0}.png", y));
Rectangle tileBounds = new Rectangle(x * tile, y * tile, tile, tile);
Bitmap target = new Bitmap(tile, tile);
using (Graphics graphics = Graphics.FromImage(target))
{
graphics.DrawImage(
image,
new Rectangle(0, 0, tile, tile),
tileBounds,
GraphicsUnit.Pixel);
}
target.Save(outputFileName, ImageFormat.Png);
}
}
}
}
}
}
Приложение 2
@model App_HSE.Models.new_floors
<head>
<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.3/leaflet.css" />
<script src="http://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.3/leaflet.js"></script>
</head>
<body>
<div>
<div id="map" style="width: 720px; height: 405px"></div>
<button onclick="plusDivs(-1)"> Предыдущий этаж</button>
<button onclick="plusDivs(1)"> Следующий этаж</button>
</div>
<script>
var mapMinZoom = 0;
var mapMaxZoom = 3;
// var counter = 0;
var popup = L.popup();
var markers = [];
mapIndex = @(ViewBag.item.floorId); // (ViewBag.item.mapLevel)
function plusDivs(n) {
mapIndex += n
//counter = 1;
if (mapIndex > 0)//&&((ViewBag.item.mapLevel))
{
window.location.href = '/new_floors/Maps/'+ mapIndex;
}
$.ajax({
type: 'GET',
url: '/new_floors/Map/'+ mapIndex,
success: function (data) {
alert(data);
}
});
}
/*function showDivs(n) {
/*$.ajax({
url: "/new_floors/Maps/"+n,
type: 'POST',
//data: { id: n }
}
}*/
var map = L.map('map', {
maxZoom: mapMaxZoom,
minZoom: mapMinZoom,
crs: L.CRS.Simple,
}).setView([-130, 60], 1);
// if (counter == 0)
// {
L.tileLayer('@(ViewBag.item.tiles)/m{z}/m{x}/{y}.png', {
continuousWorld: true,
noWrap: true,
tms: false
}).addTo(map);
// } else {
//}
map.on('click', onMapClick);
function onMapClick(e) {
popup
.setLatLng(e.latlng)
.setContent("Do you want to create node in: " + e.latlng.toString() + "?")
.openOn(map);
var Feature = {
"type": "Feature",
"properties": {},
"geometry": {
"type": "Point",
"coordinates": [e.latlng.lat, e.latlng.lng]
}
}
var marker;
L.geoJson(Feature, {
pointToLayer: function (feature, latlng) {
marker = L.marker(e.latlng).bindPopup("<input type='radio' class='marker-delete-button' value='Delete'> <br> <input type='radio' class='marker-connect-button' value='Connect'>");
// marker = L.marker(e.latlng).bindPopup("<input type='radio' value='Connect this marker' class='marker-connect-button'>");
//
lats.push(e.latlng);
marker.on("popupopen", onPopupOpen);
return marker;
}
}).addTo(map);
}
function onPopupOpen() {
var tempMarker = this;
$(".marker-delete-button:visible").click(function () {
map.removeLayer(tempMarker);
});
$(".marker-connect-button:visible").click(function () {
$.each(map._layers, function (ml) {
//console.log(map._layers)
if (map._layers[ml].feature) { markers.push(this) }})
console.log(lats);
var myLines = [{
"type": "LineString",
"coordinates": [lats[1], lats[2]]
}];
console.log(lats);
console.log(myLines);
L.geoJson(myLines).addTo(map);
//var travel = L.polyline([lats[2],lats[1]]).addTo(map);
//var polyline = L.polyline(markers, { color: 'red' }).addTo(map);
});
}
</script>
</body>
Приложение 3
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using App_HSE.Models;
namespace App_HSE.Controllers
{
public class new_floorsController: Controller
{
private DB_9DE66D_beaconsEntities db = new DB_9DE66D_beaconsEntities();
// GET: new_floors
public ActionResult Index()
{
var new_floors = db.new_floors.Include(n => n.new_builds);
return View(new_floors.ToList());
}
public ActionResult Maps(int? id)
{
new_floors new_floors = db.new_floors.Find(id);
ViewBag.item = new_floors;
//ViewBag.nodeIdFk = new SelectList(db.new_nodes, "nodeId", "nodeId");
//ViewBag.buildingIdFk = new SelectList(db.new_builds, "buildingId", "buildingId", buildingIdFk);
//int buildingIdFk = 1;
//SelectList map_floors = new SelectList(db.new_floors.Where(c => c.new_builds.buildingId == selectedIndex), "floorId", "MapLevel");
// ViewBag.map_floors = new SelectList(db.new_floors.Where(c => c.new_builds.buildingId == buildingIdFk), "floorId", "MapLevel");
//ViewBag.map_floors = new SelectList(db.new_floors.Where(c => c.buildingIdFk == buildingIdFk), "floorId", "MapLevel");
return View(new_floors);
}
public object Map(int id)
{
var data = InfoAboutBeacons(id).Select(p => new {node_id = p.nodeId, lattitude = p.coordX, longtitude = p.coordY});
return data;
}
public List<new_nodes> InfoAboutBeacons(int id)
{
var data = db.new_nodes.Where(e => e.mapIdFk == id).ToList<new_nodes>();
return data;
}
/* [HttpPost]
public JsonResult GetMap()
{
var data1 = Map();
return Json(data1, JsonRequestBehavior.AllowGet);
}
public IEnumerable<new_floors> Map()
{
return (from p in db.new_nodes
select new
{
Latitude = p.coordX,
Longitude = p.coordY,
mapIdFk = p.mapIdFk
}).ToList()
.Select(res => new new_nodes
{
mapIdFk = res.mapIdFk });
}*/
// GET: new_floors/Details/5
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
new_floors new_floors = db.new_floors.Find(id);
if (new_floors == null)
{
return HttpNotFound();
}
return View(new_floors);
}
// GET: new_floors/Create
public ActionResult Create()
{
ViewBag.buildingIdFk = new SelectList(db.new_builds, "buildingId", "buildingId");
return View();
}
// POST: new_floors/Create
// Чтобы защититься от атак чрезмерной передачи данных, включите определенные свойства, для которых следует установить привязку. Дополнительные
// сведения см. в статье http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "floorId,dir,tiles,tilesXcount,tilesYcount,mapLevel,buildingIdFk,width,height")] new_floors new_floors)
{
if (ModelState.IsValid)
{
db.new_floors.Add(new_floors);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.buildingIdFk = new SelectList(db.new_builds, "buildingId", "buildingId", new_floors.buildingIdFk);
return View(new_floors);
}
// GET: new_floors/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
new_floors new_floors = db.new_floors.Find(id);
if (new_floors == null)
{
return HttpNotFound();
}
ViewBag.buildingIdFk = new SelectList(db.new_builds, "buildingId", "buildingId", new_floors.buildingIdFk);
return View(new_floors);
}
// POST: new_floors/Edit/5
// Чтобы защититься от атак чрезмерной передачи данных, включите определенные свойства, для которых следует установить привязку. Дополнительные
// сведения см. в статье http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "floorId,dir,tiles,tilesXcount,tilesYcount,mapLevel,buildingIdFk,width,height")] new_floors new_floors)
{
if (ModelState.IsValid)
{
db.Entry(new_floors).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.buildingIdFk = new SelectList(db.new_builds, "buildingId", "buildingId", new_floors.buildingIdFk);
return View(new_floors);
}
// GET: new_floors/Delete/5
public ActionResult Delete(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
new_floors new_floors = db.new_floors.Find(id);
if (new_floors == null)
{
return HttpNotFound();
}
return View(new_floors);
}
// POST: new_floors/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
new_floors new_floors = db.new_floors.Find(id);
db.new_floors.Remove(new_floors);
db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
}
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using HseDataAccess;
using System.Web.Http.Results;
namespace HSEbeacons_web.Controllers
{
public class IbeaconController: ApiController
{
private DB_9DE66D_beaconsEntities entities = new DB_9DE66D_beaconsEntities();
//information about all beacons
[Route("api/Ibeacon/getIBeacons")]
public object GetIBeacons()
{
return (entities.new_ibeacons.ToList<new_ibeacons>()).Select(p => new { IbeaconId = p.beaconId, title = p.title, description = p.description, uuid = p.uuid, minor = p.minor, major = p.major, mapId = p.mapIdFK, coordX = p.coordX, coordY = p.coordY, nodeNum = p.nodeNum, batteryLevel = p.batteryLevel });
}
//information about beacon by id
[Route("api/Ibeacon/getIBeaconById/{id}")]
public object GetIBeaconById(int id)
{
return (entities.new_ibeacons.ToList<new_ibeacons>().Where(e => e.beaconId == id).Select(p => new { IbeaconId = p.beaconId, title = p.title, description = p.description, uuid = p.uuid, minor = p.minor, major = p.major, mapId = p.mapIdFK, coordX = p.coordX, coordY = p.coordY, nodeNum = p.nodeNum, batteryLevel = p.batteryLevel }));
}
// beacon id by uuid, minor, major
[Route("api/getibeaconbyuuid/{id}/{minor}/{major}")]
public object GetIBeaconByUuidMinorMajor(string id, int minor, int major)
{
var jsondata = entities.new_ibeacons.ToList<new_ibeacons>().Where(e => (e.uuid.Equals(id)) && (e.minor == minor)&& (e.major == major)).Select(p => new { IbeaconId = p.beaconId});
return jsondata;
}
//Information about beacons by building id
[Route("api/Ibeacon/getIBeaconsByBuildingId/{id}")]
public object GetIBeaconsByBuildingId(int id)
{
IEnumerable<new_floors> map = entities.new_floors.Where(e => e.buildingIdFk == id);//.Select(p => new { floorId = p.floorId });
List<new_ibeacons> tmp_list = new List<new_ibeacons>();
foreach (new_floors f_id in map)
{
IEnumerable<new_ibeacons> floor = entities.new_ibeacons.Where(e => e.mapIdFK == f_id.floorId);
foreach (new_ibeacons b_id in floor)
{
tmp_list.Add(b_id);
}
}
return tmp_list.Select(p => new { IbeaconId = p.beaconId, title = p.title, description = p.description, uuid = p.uuid, minor = p.minor, major = p.major, mapId = p.mapIdFK, coordX = p.coordX, coordY = p.coordY, nodeNum = p.nodeNum, batteryLevel = p.batteryLevel });
Подобные документы
Разработка клиент-серверного приложения, позволяющего взаимодействовать друг с другом с использованием доступа к базам данных. Проектирование связи сервера с базой данных с помощью технологии ODBC. Разработка интерфейса программы, ее тестирование.
курсовая работа [352,0 K], добавлен 24.08.2016Разработка клиент-серверного игрового приложения на примере игры в шашки для мобильных устройств на базе операционной системы Android. Обзор мобильных платформ. Экраны приложения и их взаимодействие. Графический интерфейс, руководство пользователя.
курсовая работа [2,6 M], добавлен 15.06.2013Разработка системы, базирующейся на протоколе LIMone, для обмена мгновенными сообщениями и пересылки файлов в процессе деловой переписки. Реализация системы в виде клиент-серверного приложения. Расчет экономических показателей программного продукта.
дипломная работа [4,7 M], добавлен 22.08.2016Сетевое программное обеспечение: общее понятие, содержание, функции. Этапы развития теории компьютерных сетей. Проектирование в среде программирования Borland Builder C++ клиент серверного приложения с использованием сокетов, листинг данной программы.
курсовая работа [191,5 K], добавлен 07.01.2015Разработка клиент-серверного приложения на основе TCP\IP соединения. Организация работы удаленного генератора псевдослучайных последовательностей. Описание основных функциональных модулей. Интерфейс пользователя, сетевое взаимодействие и алгоритм.
курсовая работа [223,6 K], добавлен 18.10.2013Разработка конфигурации службы. Исследование вычислительной эффективности алгоритма оптимизации. Программная реализация клиент-серверного приложения. Алгоритм решения непрерывной задачи загрузки рюкзака. Подключение веб-сервиса к клиентскому приложению.
курсовая работа [1,4 M], добавлен 21.01.2017Современное состояние рынка мобильных приложений. Основные подходы к разработке мобильных приложений. Обоснование выбора целевой группы потребителей приложения. Этапы проектирования и разработки мобильного приложения для операционной системы Android.
курсовая работа [987,1 K], добавлен 27.06.2019Изучение истории достижений корпорации Oracle. Разработка клиент-серверного приложения на языке Delphi XE, реализующего возможность управления персоналом на предприятии. Основные структуры данных. Создание инструкции работы с приложением "Отдел кадров".
дипломная работа [974,7 K], добавлен 08.06.2013Создание программы для мобильного устройства, для решения геометрических задач: нахождения площади треугольника по формуле Герона, площади прямоугольного треугольника и круга. Реализация программных модулей, интерфейс программы, руководство пользователя.
курсовая работа [314,9 K], добавлен 07.12.2014Анализ игровых жанров для мобильных устройств и целевой аудитории. Разработка концепции игрового приложения, основной механики, меню и интерфейса игры. Описание переменных скриптов. Реализация выбора цели и стрельбы. Настройка работоспособности игры.
дипломная работа [1,4 M], добавлен 19.01.2017