вторник, 31 августа 2010 г.

Часть 3: Становление и развитие научных исследований в области искусственного интеллекта

4. Подъем и спад исследований (1980-е)

Начало 1980-х годов казалось многообещающим для исследователей искусственного интеллекта, в эти годы значительно возросли продажи программного обеспечения и аппаратных средств, связанных с искусственным интеллектом, к 1986 году они превысили 400 000 000 долларов. Основная часть дохода получена за счет экспертных систем и LISP-машин [5].
Экспертные системы использовались многими коммерческими компаниями для диагностики, прогнозирования инвестиций, добычи полезных ископаемых и т.д. В те же годы были выявлены ограничения экспертных систем по количеству правил. Например, системный конфигуратор XCON, разработанный компанией Digital Equipment Corporation, который пользовался небывалым успехом и сохранял для компании миллионы долларов в год, содержал около 10000 правил и его техническая поддержка стала крайне трудной задачей.
В 1981 году правительство Японии инвестировано 850 млн. долларов в разработку компьютера пятого поколения, который должен был обладать интеллектуальным поведением: распознавать образы, понимать и синтезировать и переводить речь [11]. Однако уже к 1987 новые персональные компьютеры от IBM и Apple стали мощнее и дешевле LISP-машин, что разрушило данный сегмент бизнеса. А уже к 1991 году стало понятно, что надеждам, возложенным на компьютеры пятого поколения, не суждено сбыться. Финансирования не было прекращено, однако, даже к 2004 году большая часть планов не была осуществлена [12].
В 1982 году Джон Хопфилд разработал новую модель искусственных нейронных сетей (сеть Хопфилда), которая могла по-новому обрабатывать сигналы, а Дэвид Румельхарт и Пол Вербос разработали метод обратного распространения ошибки для обучения нейронных сетей. Эти открытия положили начало новой эры развития искусственных нейронных сетей, которые практически не исследовались с 1970 [13]. Они нашли применение в таких областях как распознавание речи и построение самообучающихся машин.
Искусственная жизнь как отдельное научное направление выделилась из теории искусственного интеллекта в 80-х годах, когда состоялась первая Международная конференция ALife I (1989 г., Лос-Аламос).
Вскоре за ней последовали Европейская конференция по искусственной жизни и Международная конференция по моделированию адаптивного поведения (обе —1991 г., Париж).
Тематика первых мероприятий затрагивала темы, как теперь выражаются, “мягкой” искусственной жизни — создание вычислительных систем и моделей, действующих на базе биологических и эволюционных принципов. В последние же годы, во многом в связи с развитием нанотехнологических дисциплин и молекулярной биологии, а также благодаря возросшему пониманию назначения отдельных генов и способов их взаимодействия и появлению средств манипуляции отдельными молекулами, существенное внимание стало уделяться новой концепции “влажной” искусственной жизни — созданию новых, искусственно синтезированных биологических форм, что требует философского обоснования искусственной жизни и как минимум определения понятия “жизнь” (что же вообще понимать под этим словом). В соответствии со спецификой нашего издания мы рассмотрим “мягкую” форму искусственной жизни.
Одной из главных задач искусственной жизни считается создание искусственных существ, способных действовать не менее эффективно, нежели живые организмы1. Только способы достижения этой цели существенно отличаются от общепринятых в практике искусственного интеллекта, где задействованы самые разные инженерные технологии и математические концепции (выбираемые фактически бессистемно), характеризующиеся, тем не менее, достаточно четкими и прозрачными причинно-следственными связями между исходными данными экспериментов и результирующим поведением моделируемых объектов. Так, чаще всего действия роботов основываются на системах логического вывода, выполняющих известные манипуляции с наборами фактов и правил. Нейронные сети, результат работы которых менее предсказуем, находятся на стыке искусственного интеллекта и искусственной жизни и активно задействованы представителями каждого из этих направлений, а вот такая технология, как генетические алгоритмы, сегодня по праву считается полноценной вотчиной искусственной жизни. Общепринятые же традиционные подходы, базирующиеся на компьютерной архитектуре фон Неймана и вычислительной концепции Тьюринга (хранимые в памяти и не модифицируемые программы, выполняемые последовательно), в искусственной жизни особой популярностью не пользуются.
Пожалуй, главное отличие искусственной жизни от других сфер искусственного интеллекта заключается в стремлении не просто добиться поведенческого сходства искусственных существ с биологическими, а достичь этого с помощью естественных, природных, эволюционных подходов. Тем самым не только достигается прагматический результат, но и появляется шанс познавать базовые принципы функционирования и развития живых существ “изнутри”. На такой основе и намечается переход от “мягкой” сферы исследований к “влажной” — искусственному созданию биологической жизни эволюционным путем “снизу вверх”. Поэтому закрытые решения, пусть и позволяющие добиться высокой эффективности действий робота или моделируемого объекта, в классических проектах ИЖ обычно не применяются и не представляют ценности, если не содержат информацию, помогающую познать реальный мир через познание самой модели.
Хотя, конечно, далеко не все исследователи, занимающиеся проблемами сферы искусственной жизни, стремятся к глубокому познанию реальности. Многих интересуют конкретные прикладные результаты, и хорошее соответствие действий искусственных и естественных существ уже само по себе может служить научным инструментом (за счет предсказания поведения). Поэтому значительная область искусственной жизни охватывает вопросы построения систем эволюционного, самоорганизующегося, масштабируемого, адаптивного поведения, основанных на биологических принципах. Ведь немалое число практических проблем невозможно решить точными математическими методами по самым разным причинам (неполнота исходных сведений, большое число конкурентов и противников, высокие размерность задачи и динамика действий в среде). Поэтому нередко проще смоделировать процесс развития некоторой ситуации, нежели пытаться сразу вычислить точный ответ [14].

5. Развитие искусственного интеллекта (1993 – настоящее время)

1990-е годы стали эрой развития, так называемого слабого искусственного интеллекта - систем, содержащих лишь некоторые функции, которые можно назвать интеллектуальным поведением. Такие системы интересны с коммерческой точки зрения, поскольку позволяют добиться эффективного решения многих задач при небольших материальных и временных затратах.
Получили большое распространения приложения со следующими функциями: распознавание лиц, системы автоматического планирования, системы предсказания прибыли и т.д.
В 1990-е годы появилось новое направление исследований искусственного интеллекта – интеллектуальные агенты. В искусственном интеллекте, под термином интеллектуальный агент понимаются разумные сущности, наблюдающие за окружающей средой и действующие в ней, при этом их поведение рационально в том смысле, что они способны к пониманию и их действия всегда направлены на достижение какой-либо цели. Такой агент может быть как роботом, так и встроенной программной системой. Об интеллектуальности агента можно говорить, если он взаимодействует с окружающей средой примерно так же, как действовал бы человек [15].
Важным событием в развитии искусственного интеллекта стала разработка в 1997 году компьютера для игры шахматы Deep Blue, который смог обыграть чемпиона мира по шахматам Гарри Каспарова.
Также в 1997 году проводится первый футбольный турнир между роботов RoboCup.
В 2005 году начат Blue Brain Project – проект по моделированию неокортекса (часть головного мозга) человека и исследованию работы мозга целиков [16]. Результаты, полученные в ходе работы над проектом, могу оказаться крайне важными для исследования искусственного интеллекта.
В 2007 году исследователи из университета Альберта разработали программу, которая играет в шашки и при этом никогда не проигрывает [17].
Можно предположить, что такие направления развития искусственного интеллекта как интеллектуальные агенты, многоагентные системы, системы искусственной жизни, нейронные сети и робототехника будут активно развиваться в ближайшие годы.
Ключевым фактором, определяющим сегодня развитие технологий искусственного интеллекта, считается темп роста вычислительной мощности компьютеров, так как принципы работы человеческой психики по-прежнему остаются неясными (на доступном для моделирования уровне детализации). Поэтому тематика конференций об искусственной интеллекте выглядит достаточно стандартно и по составу почти не меняется уже довольно давно. Но рост производительности современных компьютеров в сочетании с повышением качества алгоритмов периодически делает возможным применение различных научных методов на практике. Так случилось с интеллектуальными игрушками, так происходит с домашними роботами.
Снова будут интенсивно развиваться временно забытые методы простого перебора вариантов (как в шахматных программах), обходящиеся крайне упрощенным описанием объектов. Но с помощью такого подхода (главный ресурс для его успешного применения - производительность) удастся решить, как ожидается, множество самых разных задач (например, из области криптографии). Уверенно действовать автономным устройствам в сложном мире помогут достаточно простые, но ресурсоемкие алгоритмы адаптивного поведения. При этом ставится цель разрабатывать системы, не внешне похожие на человека, а действующие, как человек.
Ученые пытаются заглянуть и в более отдаленное будущее. Можно ли создать автономные устройства, способные при необходимости самостоятельно собирать себе подобные копии (размножаться)? Способна ли наука создать соответствующие алгоритмы? Сможем ли мы контролировать такие машины? Ответов на эти вопросы пока нет.
Продолжится активное внедрение формальной логики в прикладные системы представления и обработки знаний. В то же время такая логика не способна полноценно отразить реальную жизнь, и произойдет интеграция различных систем логического вывода в единых оболочках. При этом, возможно, удастся перейти от концепции детального представления информации об объектах и приемов манипулирования этой информацией к более абстрактным формальным описаниям и применению универсальных механизмов вывода, а сами объекты будут характеризоваться небольшим массивом данных, основанных на вероятностных распределениях характеристик [18].

Заключение

Несмотря на то, что история науки об искусственном интеллекте насчитывает только около 60 лет, что значительно меньше истории развития большинства современных областей науки, ее вполне можно считать самостоятельной и зрелой наукой.
Результатом работы ученых стали компьютерные программы и аппаратные средства, которые зачастую справляются со многими сложными задачами лучше, чем человек. Например, существуют программы, которые играют в триктрак, бридж, шахматы и покер значительно лучше среднего человека.
Множество прикладных функций «слабого» искусственного интеллекта уже заняли свое место в повседневной (в поисковых системах, помощниках, почтовых агентах) работе большого количества людей. Постепенно программное обеспечение, обладающее интеллектуальным поведением, берет на себя рутинную работу, которую раньше должен был выполнять человек.
Однако, как показывает история предмета, надеяться на скорое появление «сильного» искусственного интеллекта не приходится, к тому же, на сегодняшний день не существует адекватного метода оценки разумности, а разработанный Аланом Тьюрингом тест имеет ряд недостатков, описанных ранее.
Можно сделать вывод о том, что функции «слабого» искусственного интеллекта будут активно развиваться и интегрироваться в программное обеспечение и аппаратные средства в ближайшем будущем.

Список литературы

1. McCalloch W.S., Pitts W. A logical calculus of the ideas immanent in nervous activity. Bull. Math. Biophys. – 1943. – N5. – pp.115–133
2. Hebb D.O. The Organization Of Behavior. - New York: Wiley 1949. – pp. 215-217
3. Turing A. Computing machinery and Intelligence. – Mind – 1950. - №59 – pp. 433-460
4. Люгер Д.Ф. Искусственный интеллект. Стратегии и методы решения сложных проблем. – М.: Вильямс, 2005. – 29-55 с.
5. Джонс М.Т. Программирование искусственного интеллекта в приложениях. – М.: ДМК, 2006. – 16-20 с.
6. Winograd T. Procedures as a representation for data in a computer program for understanding natural language. – Massachusetts: The MIT Press, 1971. – pp. 260-280
7. SRI International. Shakey the Robot -http://www.sri.com/about/timeline/shakey.html
8. John R. Pierce, John B. Carroll, et al., Language and Machines — Computers in Translation and Linguistics. ALPAC report - Washington, DC, 1966. – pp. 112-140
9. Minsky M., Seymour P., Perceptrons: An Introduction to Computational Geometry - Cambridge MA: The MIT Press, 1972. - pp. 180-193
10. Berliner, Hans, et al. Backgammon program beats world champ, ACM SIGART Bulletin – 1980. - №69 - pp. 6–9
11. McCorduck .P. The fifth generation: Japan's computer challenge to the world. Edward Feigenbaum. CREATIVE COMPUTING – 1984. – №10 - p. 103
12. McCorduck. P. Machines Who Think (2nd ed.), Natick, MA: A. K. Peters, Ltd, 2004. - p. 441
13. Рассел С., Норвиг П. Искусственный интеллект. Современный подход. М.: Вильямс, 2007. - 25 с.
14. Бобровский C. PC Week RE – 2005. – №3 - 28 c.
15. Intelligent Agent - http://en.wikipedia.org/wiki/Intelligent_agent
16. Markram, H. The blue brain project.  Nat Rev Neurosci. – 2006. - №7 - pp.153-160
17. Chang, Kenneth. Computer Checkers Program Is Invincible - New York Times - 2007. - http://www.nytimes.com/2007/07/19/science/19cnd-checkers.html?hp.
18. Бобровский С. PC Week RE – 2001. - №32 - 32 с.

понедельник, 30 августа 2010 г.

Часть 2: Становление и развитие научных исследований в области искусственного интеллекта

2. Бурный рост исследований искусственного интеллекта (1950е-1970е)

Годы после Дартмутского семинара стали годами открытий, исследователи были полны оптимизма.
За первыми успешными разработками Ньюэлла и Саймона последовало создание программы общего решателя задач (General Problem Solver— GPS). В отличие от программы Logic Theorist, эта программа с самого начала была предназначена для моделирования процедуры решения задач человеком. Как оказалось, в пределах того ограниченного класса головоломок, которые была способна решать эта программа, порядок, в котором она рассматривала подцели и возможные действия, был аналогичен тому подходу, который применяется людьми для решения таких же проблем. Поэтому программа GPS была, по-видимому, самой первой программой, в которой был воплощен подход к "организации мышления по такому же принципу, как и у человека". Результаты успешного применения GPS и последующих программ в качестве модели познания позволили сформулировать знаменитую гипотезу физической символической системы, в которой утверждается, что существует "физическая символическая система, которая имеет необходимые и достаточные средства для интеллектуальных действий общего вида". Под этим подразумевается, что любая система, проявляющая интеллект (человек или машина), должна действовать по принципу манипулирования структурами данных, состоящими из символов.
Джон Маккарти перешел из Дартмутского университета в Массачусетсский технологический институт и здесь в течение одного исторического 1958 года внес три крайне важных вклада в развитие искусственного интеллекта. В документе MIT AI Lab Memo No. 1 Джон Маккарти привел определение нового языка высокого уровня Lisp, которому суждено было стать доминирующим языком программирования для искусственного интеллекта. Lisp остается одним из главных языков высокого уровня, применяемых в настоящее время, будучи вместе с тем вторым по очередности появления языком такого типа, который был создан всего на один год позже чем Fortran. Разработав язык Lisp, Маккарти получил необходимый для него инструмент, но доступ к ограниченным и дорогостоящим компьютерным ресурсам продолжал оставаться серьезной проблемой. В связи с этим он совместно с другими сотрудниками Массачусетсского технологического института изобрел режим разделения времени. В том же 1958 году Маккарти опубликовал статью под названием Programs with Common Sense, в которой он описал гипотетическую программу Advice Taker, которая может рассматриваться как первая полная система искусственного интеллекта. Как и программы Logic Theorist и Geometry Theorem Prover, данная программа Маккарти была предназначена для использования знаний при поиске решений задач. Но в отличие от других программ она была предназначена для включения общих знаний о мире. Например, Маккарти показал, что некоторые простые аксиомы позволяют этой программе разработать план оптимального маршрута автомобильной поездки в аэропорт, чтобы можно было успеть на самолет. Данная программа была также спроектирована таким образом, что могла принимать новые аксиомы в ходе обычной работы, а это позволяло ей приобретать компетентность в новых областях без перепрограммирования. Таким образом, в программе Advice Taker были воплощены центральные принципы представления знаний и проведения рассуждений, которые заключаются в том, что всегда полезно иметь формальное, явное представление о мире, а также о том, как действия агента влияют на этот мир и как приобрести способность манипулировать подобными представлениями с помощью дедуктивных процессов. Замечательной особенностью указанной статьи, которая вышла в 1958 году, является то, что значительная ее часть не потеряла своего значения и в наши дни.
В конце 1950-х Джон МакКарти и Марвин Мински основали в MIT лабораторию искусственного интеллекта, которая работает и сегодня [5].
В 1958 году Фрэнк Розенблатт опубликовал работу «The Perceptron: A Probabilistic Model for Information Storage and Organization in the Brain», в которой развил идеи Хебба об обучении искусственных нейронной и предложил устройство, моделирующее процесс человеческого восприятия. Розенблатт назвал это устройство «перцептроном». Перцептрон передавал сигналы от фотоэлементов, представляющих собой сенсорное поле, в блоки электромеханических ячеек памяти. Эти ячейки соединялись между собой случайным образом в соответствии с принципами коннективизма. В 1957 году в Корнелльской Лаборатории Аэронавтики успешно было завершено моделирование работы перцептрона на компьютере IBM 704, а два года спустя, 23 июня 1960 года в Корнелльском университете, был продемонстрирован первый нейрокомпьютер — «Марк-1», который был способен распознавать некоторые из букв английского алфавита.
Чтобы «научить» перцептрон классифицировать образы, был разработан специальный итерационный метод обучения проб и ошибок, напоминающий процесс обучения человека — метод коррекции ошибки. Кроме того, при распознании той или иной буквы перцептрон мог выделять характерные особенности буквы, статистически чаще встречающиеся, чем малозначимые отличия в индивидуальных случаях. Тем самым перцептрон был способен обобщать буквы, написанные различным образом (почерком), в один обобщённый образ. Однако возможности перцептрона были ограниченными: машина не могла надежно распознавать частично закрытые буквы, а также буквы иного размера, расположенные со сдвигом или поворотом, нежели те, которые использовались на этапе ее обучения.
В 1960-е одной из наиболее важных областей разработки стало представление знаний. Терри Виноград разработал программу SHRDLU [6], при помощи которой тестировались идеи по машинному зрению, робототехнике и обработке естественного языка. Программа понимала простые команды («Поставь зеленый блок на синий») и могла ответить на рад вопросов о своих действиях («Зачем ты передвинул зеленый блок?»).
В начале 1960-х Джон МакКарти основал лабораторию искусственного интеллекта в Стэнфордском университете, в которой был разработан робот Шейки (Shakey), который мог перемещаться по искусственному миру и выполнять простые программы [7].

3. Спад исследований искусственного интеллекта (1970-е)

Чрезмерный оптимизм исследователей не оправдался, они не смогли выполнить своих обещаний, системы, основанные на искусственном интеллекте, не показывали обещанных результатов.
Можно выделить несколько основных причин спада:
Машинный перевод. Во времена Холодной войны правительство США было крайне заинтересовано в автоматическом переводе русскоязычных текстов и научных документов. С 1954 года началось активное финансирование в разработку систем машинного перевода, а ученые заявляли, что находятся на грани прорыва в науке. Однако, в ходе исследований были выявлены проблемы, которые не позволяли сделать машинные переводы достаточно эффективными и в 1964 году была создана комиссия ALPAC (Automatic Language Processing Advisory Committee), опубликовавшая в 1966 году отчет, согласно которому машинный перевод оказался менее эффективным и более дорогим, чем перевод человеком [8]. В связи с этим исследования машинного перевода были прекращены.
Нейронные сети. В 1969 году Матрин Мински и Сеймур Паперт опубликовали книгу «Perceptrons: An Introduction to Computational Geometry», которая описывала ограничения по использованию однослойных перцептронов, что привело к значительному снижению интереса к нейронным сетям более чем на 10 лет [9].
Окончание финансирования исследований. 1969 году Майк Мэнсфилд фактически прекратил финансирование исследований в область искусственного интеллекта со стороны DARPA. Финансировались только проекты, которые обещали быть в скором времени полезными для вооруженных сил США.
С другой стороны в 1970-е годы получили развитие системы, основанные знаниях, в особенности это были системы, которые обладали знаниями в какой-то конкретной области и могли строить достаточно длинные цепочки рассуждений для того, чтобы в достаточной точностью найти ответ на поставленный вопрос.
Одним из первых примеров реализации такого подхода была программа Dendral . Она была разработана в Станфордском университете группой ученых, в которую вошли Эд Фейгенбаум (бывший студент Герберта Саймона), Брюс Бьюкенен (философ, который сменил специальность и стал заниматься компьютерными науками) и Джошуа Ледерберг (лауреат Нобелевской премии в области генетики). Эта группа занималась решением проблемы определения структуры молекул на основе информации, полученной от масс-спектрометра. Вход этой программы состоял из химической формулы соединения (например, C6H13N02) и спектра масс, позволяющего определять массы различных фрагментов молекулы, который формировался при бомбардировке молекулы потоком электронов. Например, спектр масс может содержать пик в точке m=15, соответствующий массе метилового фрагмента (СН3).
Первая, примитивная версия этой программы предусматривала выработку всех возможных структур, совместимых с данной формулой, после чего предсказывала, какой спектр масс должен наблюдаться для каждой из этих структур, сравнивая его с фактическим спектром. Вполне можно ожидать, что такая задача применительно к молекулам более крупных размеров становится неразрешимой. Поэтому разработчики программы Dendral проконсультировались с химиками-аналитиками и пришли к выводу, что следует попытаться организовать работу по принципу поиска широко известных картин расположения пиков в спектре, которые указывают на наличие общих подструктур в молекуле. Например, для распознавания кетоновых подгрупп (С=0) с атомными весами 28 может использоваться приведенное ниже правило.
ЕСЛИ имеются два пика в точках x1 и х2, такие, что:
а)   x1 + х2 = М + 28 (где M—масса всей молекулы);
б)  в точке x1 - 28 — высокий пик;
в)   в точке x2 - 28 — высокий пик;
г)   по меньшей мере в одной из точек x1 и х2 — высокий пик, ТОГДА существует кетоновая подгруппа.
Применение способа, предусматривающего распознавание того, что молекула содержит какие-то конкретные подструктуры, позволило весьма значительно сократить количество возможных кандидатов, подлежащих проверке. В конечном итоге программа Dendral оказалась очень мощной, и причины этого описаны ниже.
Значение программы Dendral состояло в том, что это была первая успешно созданная экспертная система, основанная на широком использовании знаний: ее способность справляться с поставленными задачами была обусловлена применением большого количества правил специального назначения. В более поздних системах также широко применялся основной принцип подхода, реализованного Маккарти в программе Advice Taker, — четкое отделение знаний (в форме правил) от компонента, обеспечивающего проведение рассуждений.
Руководствуясь этим опытом, Фейгенбаум и другие специалисты из Станфорд-ского университета приступили к разработке проекта эвристического программирования (Heuristic Programming Project— HPP), целью которого было исследование того, в какой степени созданная ими новая методология экспертных систем может быть применена в других областях интеллектуальной деятельности человека. На очередном этапе основные усилия были сосредоточены в области медицинской диагностики. Фейгенбаум, Бьюкенен и доктор Эдвард Шортлифф разработали программу Mycin для диагностики инфекционных заболеваний кровеносной системы. После ввода в нее примерно 450 правил программа Mycin приобрела способность работать на уровне некоторых экспертов, а также показала значительно более лучшие результаты по сравнению с врачами, имеющими не такой большой стаж. Она также обладала двумя важными отличительными особенностями по сравнению с программой Dendral. Во-первых, в отличие от правил Dendral не существовала общая теоретическая модель, на основании которой мог бы осуществляться логический вывод правил Mycin. Для выявления этих правил приходилось широко применять знания, полученные от экспертов, которые, в свою очередь, приобретали эти знания с помощью учебников, других экспертов и непосредственного опыта, накопленного путем изучения практических случаев. Во-вторых, в этих правилах приходилось учитывать ту степень неопределенности, которой характеризуются знания в области медицины. В программе Mycin применялось исчисление неопределенностей на основе так называемых коэффициентов уверенности, которое (в то время) казалось вполне соответствующим тому, как врачи оценивают влияние объективных данных на диагноз.
В связи с широким ростом количества приложений, предназначенных для решения проблем реального мира, столь же широко возрастали потребности в создании работоспособных схем представления знаний. Было разработано большое количество различных языков для представления знаний и проведения рассуждений. Некоторые из них были основаны на логике, например, в Европе получил распространение язык Prolog, а в Соединенных Штатах широко применялось семейство языков Planner. В других языках, основанных на выдвинутой Минским идее фреймов, был принят более структурированный подход, предусматривающий сбор фактов о конкретных типах объектов и событий, а также упорядочение этих типов в виде крупной таксономической иерархии, аналогичной биологической таксономии.
В 1979 году Ганс Берлинер разработал программу для игры в триктрак, которая смогла победить чемпиона мира по триктраку, Луиджи Вилла из Италии. Это был первый случай победы компьютерной программы над человеком в сложной игре [10].

Часть 1: Становление и развитие научных исследований в области искусственного интеллекта

 
В этой статье мы рассмотрим историю развития искусственного интеллекта.

Введение

Искусственный интеллект — это одна из новейших областей науки. Первые работы в этой области начались вскоре после Второй мировой войны, а само ее название было предложено в 1956 году. Ученые других специальностей чаще всего указывают искусственный интеллект, наряду с молекулярной биологией, как «область, в которой я больше всего хотел бы работать». Студенты-физики вполне обоснованно считают, что все великие открытия в их области уже были сделаны Галилеем, Ньютоном, Эйнштейном и другими учеными. Искусственный интеллект, с другой стороны, все еще открывает возможности для проявления талантов нескольких настоящих Эйнштейнов.
В настоящее время тематика искусственного интеллекта охватывает огромный перечень научных направлений, начиная с таких задач общего характера, как обучение и восприятие, и заканчивая такими специальными задачами, как игра в шахматы, доказательство математических теорем, сочинение поэтических произведений и диагностика заболеваний. В искусственном интеллекте систематизируются и автоматизируются интеллектуальные задачи и поэтому эта область касается любой сферы интеллектуальной деятельности человека. В этом смысле искусственный интеллект является поистине универсальной научной областью.
Можно условно разделить история развития науки об искусственном интеллекте на несколько временных отрезков:
1. рождение искусственного интеллекта
2. бурный рост исследований
3. спад исследований
4. новый рост и спад исследований
5. Современное состояние науки об искусственном интеллекте
В данной работе будет подробно рассмотрен каждый из выделенных периодов времени.

1. Рождение искусственного интеллекта (1940е-1950е)

Первой работой, посвященной вопросам разработки искусственного интеллекта, считается статья Уоррена Мак-Каллока и Уолтера Питтса «A Logical Calculus of the Ideas Immanent in Nervous Activity» («Логическое исчисление идей, относящихся к нервной активности»), написанная в 1943 году. Исследователи основывались на знании физиологии человека и структуры человеческого мозга, они полагали, что смоделировав нейроны человеческого мозга можно смоделировать интеллектуальную деятельность. В работе было введено понятие искусственного нейрона, показано, что из искусственных нейронов могут быть составлены логические элементы (такие как «И», «ИЛИ», «НЕ»), а также высказано предположение, что искусственные нейроны и сети, составленные из них, способны обучаться [1]. Позднее, в 1949 году, Дональд Хебб предложил первый работающий алгоритм обучения искусственных нейронных сетей [2]. Данное правило лежит в основе современных методов обучения искусственных нейронов и носит название «хеббовское обучение».
Два аспиранта факультета математики Принстонского университета, Марвин Минский и Дин Эдмондс, в 1951 году создали первый сетевой компьютер на основе нейронных сетей. В этом компьютере, получившем название Snare, использовалось 3000 электронных ламп и дополнительный механизм автопилота с бомбардировщика В-24 для моделирования сети из 40 нейронов.
Одной из наиболее важных работ в области искусственного интеллекта считается работа Алана Тьюринга «Computing Machinery and Intelligence», опубликованная в 1950 году. Не смотря на то, что с момента публикации прошло более 50 лет работа все еще является актуальной. В работе Тьюринг ставил вопросы об искусственном интеллекте и сам отвечает на них: может ли машина думать? Что значит «думать»? Сможет ли человек отличить «думающую» машину от человека? Тьюринг описывает основы машинного обучения, генетических алгоритмов, обучения с подкреплением [3], однако возможно, что наиболее ценным понятием введенным Аланом Тьюрингом является специальный тест, получивший позднее название «тест Тьюринга», целью которого является распознавание разумной деятельности. Тест Тьюринга сравнивает способности предположительно разумной машины со способностями человека - лучшим и единственным стандартом разумного поведения. В тесте, который Тьюринг назвал "имитационной игрой", машину и ее человеческого соперника (следователя) помещают в разные комнаты, отделенные от комнаты, в которой находится "имитатор". Следователь не должен видеть их или говорить с ними напрямую - он сообщается с ними исключительно с помощью текстового устройства, например, компьютерного терминала. Следователь должен отличить компьютер от человека исключительно на основе их ответов на вопросы, задаваемые через это устройство. Если же следователь не может отличить машину от человека, тогда, как утверждает Тьюринг, машину можно считать разумной.
Изолируя следователя от машины и другого человека, тест исключает предвзятое отношение - на решение следователя не будет влиять вид машины или ее электронный голос. Следователь волен задавать любые вопросы, не важно, насколько окольные или косвенные, пытаясь раскрыть "личность" компьютера. Например, следователь может попросить обоих подопытных осуществить довольно сложный арифметический подсчет, предполагая, что компьютер скорее даст верный ответ, чем человек. Чтобы обмануть эту стратегию, компьютер должен знать, когда ему следует выдать ошибочное число, чтобы показаться человеком. Чтобы обнаружить человеческое поведение на основе эмоциональной природы, следователь может попросить обоих субъектов высказаться по поводу стихотворения или картины. Компьютер в таком случае должен знать об эмоциональном складе человеческих существ.
Этот тест имеет следующие важные особенности.
1. Дает объективное понятие об интеллекте, т.е. реакции заведомо разумного существа на определенный набор вопросов. Таким образом, вводится стандарт для определения интеллекта, который предотвращает неминуемые дебаты об "истинности" его природы.
2. Препятствует заведению нас в тупик сбивающими с толку и пока безответными вопросами, такими как: должен ли компьютер использовать какие-то конкретные внутренние процессы, или же должна ли машина по-настоящему осознавать свои действия.
3. Исключает предвзятость в пользу живых существ, заставляя опрашивающего сфокусироваться исключительно на содержании ответов на вопросы.
Благодаря этим преимуществам, тест Тьюринга представляет собой хорошую основу для многих схем, которые используются на практике для испытания современных интеллектуальных программ. Программа, потенциально достигшая разумности в какой-либо предметной области, может быть испытана сравнением ее способностей по решению данного множества проблем со способностями человеческого эксперта. Этот метод испытания всего лишь вариация на тему теста Тьюринга: группу людей просят сравнить "вслепую" ответы компьютера и человека. Эта методика стала неотъемлемым инструментом, как при разработке, так и при проверке современных экспертных систем.
Тест Тьюринга, несмотря на свою интуитивную притягательность, уязвим для многих оправданных нападок. Одно из наиболее слабых мест - пристрастие в пользу чисто символьных задач. Тест не затрагивает способностей, требующих навыков перцепции или ловкости рук, хотя подобные аспекты являются важными составляющими человеческого интеллекта. Иногда же, напротив, тест Тьюринга обвиняют в попытках втиснуть машинный интеллект в форму интеллекта человеческого. Быть может, машинный интеллект просто настолько отличается от человеческого, что проверять его человеческими критериями - фундаментальная ошибка? Нужна ли нам, в самом деле, машина, которая бы решала математические задачи так же медленно и неточно, как человек? Не должна ли разумная машина извлекать выгоду из своих преимуществ, таких как большая, быстрая, надежная память, и не пытаться сымитировать человеческое познание? Все же тест Тьюринга представляется нам важной составляющей в тестировании и "аттестации" современных интеллектуальных программ [4].
В Принстонском университете проводил свои исследования еще один авторитетный специалист в области искусственного интеллекта, Джон Маккарти. После получения ученой степени Маккарти перешел в Дартмутский колледж, который и стал официальным местом рождения этой области знаний. Маккарти уговорил Марвина Минского, Клода Шеннона и Натаниэля Рочестера, чтобы они помогли ему собрать всех американских исследователей, проявляющих интерес к теории автоматов, нейронным сетям и исследованиям интеллекта. Они организовывали двухмесячный семинар в Дартмуте летом 1956 года. Всего на этом семинаре присутствовали 10 участников, включая Тренчарда Мура из Принстонского университета, Артура Самюэла из компании IBM, а также Рея Соломонова и Оливера Селфриджа из Массачусетсского технологического института (Massachussets Institute of Technlogies — MIT).
Два исследователя из технологического института Карнеги, Аллен Ньюэлл и Герберт Саймон, буквально монополизировали все это представление. Тогда как другие могли лишь поделиться своими идеями и в некоторых случаях показать программы для таких конкретных приложений, как шашки, Ньюэлл и Саймон уже могли продемонстрировать программу, проводящую рассуждения, Logic Theorist (LT), или логик-теоретик, в отношении которой Саймон заявил: "Мы изобрели компьютерную программу, способную мыслить в нечисловых терминах и поэтому решили почтенную проблему о соотношении духа и тела". Вскоре после этого семинара программа показала свою способность доказать большинство теорем из главы 2 труда Рассела и Уайтхеда Principia Mathematica. Сообщали, что Рассел пришел в восторг, когда Саймон показал ему, что эта программа предложила доказательство одной теоремы, более короткое, чем в Principia. Редакторы Journal of Symbolic Logic оказались менее подверженными эмоциям; они отказались принимать статью, в качестве соавторов которой были указаны Ньюэлл, Саймон и программа Logic Theorist.
Дартмутский семинар не привел к появлению каких-либо новых крупных открытий, но позволил познакомиться всем наиболее важным деятелям в этой научной области. Они, а также их студенты и коллеги из Массачусетсского технологического института, Университета Карнеги—Меллона, Станфордского университета и компании IBM занимали ведущее положение в этой области в течение следующих 20 лет. Возможно, дольше всего сохранившимся результатом данного семинара было соглашение принять новое название для этой области, предложенное Маккарти, — искусственный интеллект. Возможно, лучше было бы назвать эту научную область "вычислительная рациональность", но за ней закрепилось название "искусственный интеллект".
Анализ предложений по тематике докладов для Дартмутского семинара позволяет понять, с чем связана необходимость преобразовать искусственный интеллект в отдельную область знаний. Почему нельзя было бы публиковать все работы, выполненные в рамках искусственного интеллекта, под флагом теории управления, или исследования операций, или теории решений, которые в конечном итоге имеют цели, аналогичные искусственному интеллекту? Или почему искусственный интеллект не рассматривается как область математики? Ответом на эти вопросы, во-первых, является то, что искусственный интеллект с самого начала впитал идею моделирования таких человеческих качеств, как творчество, самосовершенствование и использование естественного языка. Эти задачи не рассматриваются ни в одной из указанных областей. Во-вторых, еще одним ответом является методология. Искусственный интеллект — это единственная из перечисленных выше областей, которая, безусловно, является одним из направлений компьютерных наук (хотя в исследовании операций также придается большое значение компьютерному моделированию), кроме того, искусственный интеллект — это единственная область, в которой предпринимаются попытки создания машин, действующих автономно в сложной, изменяющейся среде.

воскресенье, 29 августа 2010 г.

Часть 4:Система удаленного управления приложениями персонального компьютера с помощью мобильных устройств

В результате работы, описанной в статьях раннее, была спроектирована система, абстрагированная от среды передачи данных и модульная, позволяющая разработчикам создавать собственные расширения, покрывая недостающую функциональность и обеспечивая поддержку новых приложений, а так же позволяя разрабатывать модули работы с появляющимися новыми или редкими средами передачи данных. Так же, в рамках данной работы, было разработано тестовое приложение, демонстрирующее работу системы и являющееся в какой-то мере, обучающим, показывающим формат сообщений, которыми обмениваются сервер и клиент.
В дальнейшем, планируется добавление новой функциональности, такой, как обмен сервера и клиента сообщениями в формате XML, реализация Bluetooth сервиса, возможность возврата плагином не только текстовой информации, но и информации других типов, например, изображений, реализация "обратного сообщения", то есть управление мобильным устройством, например КПК, с помощью компьютера.
Далее я приведу исходные коды разработанного приложения.

Код класса UIEngine

using System;
using System.Windows.Forms;
using System.Drawing;
using rpcmsdk;
namespace ControllerServer
{
public class UIEngine
{
private MainForm mainForm;
private ClientsForm clientsForm;
private HelpForm helpForm;
private PluginsForm pluginsForm;
private static UIEngine instance;
public static UIEngine Instance
{
get
{
if (instance == null) instance = new UIEngine();
return instance;
}
}
private UIEngine()
{
//
// TODO: Add constructor logic here
//
Engine.Instance.ServerStarted += new EventHandler(engine_ServerStarted);
Engine.Instance.ServerStopped +=new EventHandler(engine_ServerStopped);
Engine.Instance.ClientConnected += new EventHandler(engine_ClientConnected);
Engine.Instance.PluginsLoaded +=new EventHandler(engine_PluginsLoaded);
Engine.Instance.ClientDisconnected += new EventHandler(engine_ClientDisconnected);
}
public void Run()
{
Logger.Instance.LogToConsole("UIEngine.Run:");
mainForm = new MainForm();
mainForm.Show();
mainForm.mainFormToolBar.ButtonClick += new ToolBarButtonClickEventHandler(mainFormToolBar_ButtonClick);
clientsForm = new ClientsForm();
helpForm = new HelpForm();
pluginsForm = new PluginsForm();
}
private void engine_ClientConnected(object sender, EventArgs e)
{
Client client = e as Client;
ClientListViewItem lvi = new ClientListViewItem();
lvi.Text = "Client";
lvi.Client = client;
lvi.SubItems.Add(client.GetService().GetName());
lvi.SubItems.Add(client.GetDescription());
clientsForm.clientListView.Items.Add(lvi);
}
private void mainFormToolBar_ButtonClick(object sender, ToolBarButtonClickEventArgs e)
{
if (e.Button == mainForm.startToolBarButton)
{
startStopServer(e.Button);
}
if (e.Button == mainForm.clientsToolBarButton)
{
clientsForm.Visible = true;
}
if (e.Button == mainForm.pluginsToolBarButton)
{
pluginsForm.Visible = true;
}
if (e.Button == mainForm.helpToolBarButton)
{
//helpForm.Visible = true;
helpForm.ShowDialog();
}
if (e.Button == mainForm.minimizeToolBarButton)
{
mainForm.Visible = false;
clientsForm.lastVisible = clientsForm.Visible;
clientsForm.Visible = false;
helpForm.lastVisible = helpForm.Visible;
helpForm.Visible = false;
}
if (e.Button == mainForm.closeToolBarButton)
{
Engine.Instance.StopServer();
Application.Exit();
}
}
private void startStopServer(ToolBarButton button)
{
if (!Engine.Instance.Started)
{
//engine.LoadPlugins();
button.ImageIndex = 1;
button.Pushed = true;
Engine.Instance.LoadPlugins();
//serverStarted = engine.StartServer();
Engine.Instance.StartServer();
}
else
{
//engine.StopServer();
DialogResult dr = MessageBox.Show("Are you sure?","Stop Server",MessageBoxButtons.YesNo , MessageBoxIcon.Question);
if (dr == DialogResult.Yes)
{
Engine.Instance.StopServer();
}
}
// TODO THIS CAN BE PLACED INTO Engine.Started and Engine.Stopped handlers
if (Engine.Instance.Started)
{
//Icon i = new Icon("green.ico");
Icon i = new Icon(this.GetType().Assembly.GetManifestResourceStream("ControllerServer.Resources.green.ico"));
mainForm.mainNotifyIcon.Icon = i;
//startBtn.Text = XRes.GetString("STOP_SERVER_BTN");
//startBtn.BackColor = Color.LightCoral;
}
else
{
//Icon i = new Icon("red.ico");
Icon i = new Icon(this.GetType().Assembly.GetManifestResourceStream("ControllerServer.Resources.red.ico"));
mainForm.mainNotifyIcon.Icon = i;
button.ImageIndex = 0;
button.Pushed = false;
//startBtn.Text = XRes.GetString("START_SERVER_BTN");
//startBtn.BackColor = Color.MediumSpringGreen;
}
}
private void engine_PluginsLoaded(object sender, EventArgs e)
{
pluginsForm.pluginsListView.Items.Clear();
RPCMPluginHolder[] phArr = Engine.Instance.Plugins;
ListViewItem lvi = null;
foreach (RPCMPluginHolder ph in phArr)
{
lvi = new ListViewItem();
lvi.Text = ph.Name;
lvi.SubItems.Add(ph.GUID);
String commands = "";
foreach (String s in ph.CommandsList)
{
commands += s + "; ";
}
lvi.SubItems.Add(commands);
lvi.SubItems.Add(ph.Description);
lvi.SubItems.Add(ph.About);
pluginsForm.pluginsListView.Items.Add(lvi);
}
}
private void engine_ServerStarted(object sender, EventArgs e)
{
}
private void engine_ServerStopped(object sender, EventArgs e)
{
pluginsForm.pluginsListView.Items.Clear();
clientsForm.clientListView.Items.Clear();
}
private void engine_ClientDisconnected(object sender, EventArgs e)
{
Client client = e as Client;
if (client == null) return;
foreach (ClientListViewItem clvi in clientsForm.clientListView.Items)
{
if (client.Equals(clvi.Client))
{
clientsForm.clientListView.Items.Remove(clvi);
}
}
}
}
}


Код класса Engine

using System;
using System.Collections;
using System.Windows.Forms;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Net.Sockets;
using rpcmsdk;
namespace ControllerServer
{
/// <summary>
/// Summary description for Engine.
/// </summary>
public class Engine
{
public event EventHandler PluginsLoaded;
public event EventHandler ClientConnected;
public event EventHandler ClientDisconnected;
public event EventHandler ServerStarted;
public event EventHandler ServerStopped;
private event EventHandler DataReceived;
private EventHandler dataSendRequiredEventHandler;
private Thread watchDogThread;
private bool started;
public bool Started
{
get
{
return started;
}
}
//private LANService ls;
private ArrayList clientsAL;
//private NetworkDataParser dataParser;
private static Engine instance;
public static Engine Instance
{
get
{
if (instance == null) instance = new Engine();
return instance;
}
}
public RPCMPluginHolder[] Plugins
{
get
{
return pluginsAL == null ? null : (RPCMPluginHolder[])(pluginsAL.ToArray(typeof(RPCMPluginHolder)));
}
}
private ArrayList pluginsAL;
private ArrayList servicesAL;
private Engine()
{
//
// TODO: Add constructor logic here
//
//dataParser = new NetworkDataParser();
dataSendRequiredEventHandler = new EventHandler(DataSendRequiredHandler);
clientsAL = new ArrayList();
servicesAL = new ArrayList();
}
public void OnClientConnected(EventArgs e)
{
if(ClientConnected != null)
ClientConnected(this, e);
}
public void OnClientDisconnected(EventArgs e)
{
Client client = e as Client;
clientsAL.Remove(client);
client.CloseConnection();
if(ClientDisconnected != null)
ClientDisconnected(this, e);
}
public void OnPluginsLoaded(EventArgs e)
{
Logger.Instance.LogToConsole("Engine.OnPluginsLoaded");
if(PluginsLoaded != null)
PluginsLoaded(this, e);
}
public void OnServerStarted(EventArgs e)
{
if(ServerStarted != null)
ServerStarted(this, e);
}
public void OnServerStopped(EventArgs e)
{
if(ServerStopped != null)
ServerStopped(this, e);
}
public bool StartServer()
{
System.GC.Collect();
started = false;
Logger.Instance.LogToConsole("Engine.ServerStart");
/*ls = new LANService();
//Safe because it is safe in LANService.Stop()
ls.ClientConnected += new EventHandler(ClientConnectedHandler);
ls.Initialize();
started = started || ls.Start();*/
LoadServices();
if (servicesAL != null)
foreach(RPCMNetworkService ns in servicesAL)
{
started = ns.Start() | started;
}
watchDogThread = new Thread(new ThreadStart(WatchDogThreadProc));
watchDogThread.Start();
OnServerStarted(null);
return started;
}
public void StopServer()
{
started = false;
//if (ls != null) ls.Stop();
if (clientsAL != null)
foreach(Client client in clientsAL)
{
if (client != null)
client.CloseConnection();
}
clientsAL.Clear();
if (servicesAL != null)
foreach(RPCMNetworkService ns in servicesAL)
{
ns.Stop();
}
if (watchDogThread != null && watchDogThread.IsAlive) watchDogThread.Interrupt();
OnServerStopped(null);
}
public void LoadServices()
{
//if (servicesAL != null)
/*foreach (RPCMPluginHolder ph in pluginsAL)
{
ph.Plugin.DataSendRequired -= dataSendRequiredEventHandler;
}*/
// PluginHolder objects are not deleted if handler link is alive
//DataReceived = null;
DirectoryInfo di = new DirectoryInfo(Application.StartupPath+"\\services\\");
FileInfo[] fiarr = di.GetFiles("*.dll");
servicesAL = new ArrayList();
foreach (FileInfo fi in fiarr)
{
try
{
Assembly a = Assembly.LoadFrom(fi.FullName);
foreach (Type t in a.GetExportedTypes())
{
System.Console.WriteLine(t.Name);
}
RPCMNetworkService ns = (RPCMNetworkService)a.CreateInstance("RPCMNetworkServiceNamespace.RPCMNetworkServiceInstance", true);
ns.ClientConnected += new EventHandler(ClientConnectedHandler);
servicesAL.Add(ns);
ns.Initialize();
}
catch (Exception ex)
{
Logger.Instance.LogException(ex);
Logger.Instance.PopupErrorMessage(/*MainForm.XRes.GetString(*/"CANT_LOAD_PLUGIN"/*)*/ + "\n" +fi.FullName);
}
}
}
public void UnloadServices()
{
}
public void LoadPlugins()
{
if (pluginsAL != null)
foreach (RPCMPluginHolder ph in pluginsAL)
{
ph.Plugin.DataSendRequired -= dataSendRequiredEventHandler;
}
// PluginHolder objects are not deleted if handler link is alive
DataReceived = null;
DirectoryInfo di = new DirectoryInfo(Application.StartupPath+"\\plugins\\");
FileInfo[] fiarr = di.GetFiles("*.dll");
pluginsAL = new ArrayList();
foreach (FileInfo fi in fiarr)
{
try
{
Assembly a = Assembly.LoadFrom(fi.FullName);
foreach (Type t in a.GetExportedTypes())
{
System.Console.WriteLine(t.Name);
}
RPCMPlugin p = (RPCMPlugin)a.CreateInstance("RPCMPluginNamespace.RPCMPluginInstance", true);
DataReceived += new EventHandler(p.DataReceivedHandler);
p.DataSendRequired += dataSendRequiredEventHandler/*new EventHandler(DataSendRequiredHandler)*/;
RPCMPluginHolder ph = new RPCMPluginHolder(p);
pluginsAL.Add(ph);
}
catch (Exception ex)
{
Logger.Instance.LogException(ex);
Logger.Instance.PopupErrorMessage(/*MainForm.XRes.GetString(*/"CANT_LOAD_PLUGIN"/*)*/ + "\n" +fi.FullName);
}
}
OnPluginsLoaded(null);
}
public void ClientConnectedHandler(object sender, EventArgs e)
{
Client client = e as Client;
client.DataBytesReceived += new DataBytesReceivedHandler(DataBytesReceived);
clientsAL.Add(client);
OnClientConnected(client);
Logger.Instance.LogToConsole("Engine: Client Connected! " + client.ToString());
}
public void DataBytesReceived(object sender, byte[] dataBytes)
{
Logger.Instance.LogToConsole("Engine.DataBytesReceived");
//Monitor.Wait(dataParser);
//Monitor.Enter(dataParser);
RPCMData data = NetworkDataParser.BytesToData(dataBytes);
HandleData(sender as Client, data);
if (DataReceived != null)
DataReceived(sender as Client, data);
//Monitor.Exit(dataParser);
//Monitor.Pulse(dataParser);
}
private void HandleData(Client client,RPCMData data)
{
Logger.Instance.LogToConsole("Engine.HandleData");
//TODO
if (data == null) return;
if (data.MessageType == (int)MessageTypes.Test)
{
Logger.Instance.LogToConsole("Engine.HandleData: data.MessageType == Test");
client.SendData(new byte[4]{(byte)'t',(byte)'e',(byte)'s',(byte)'t'});
}
if (data.MessageType == (int)MessageTypes.PluginsDescriptionRequired)
{
Logger.Instance.LogToConsole("Engine.HandleData: data.MessageType == PluginDescriptionRequired");
RPCMPluginHolder[] pluginsHolders = this.Plugins;
int count = pluginsHolders.Length;
RPCMData dataToSend = null;
for (int i = 0; i < count; i++)
{
dataToSend = new RPCMData();
dataToSend.GUID = pluginsHolders[i].GUID;
dataToSend.MessageType = (int)MessageTypes.PluginDescription;
String description = pluginsHolders[i].Name + "#" + pluginsHolders[i].Description;
int counter = pluginsHolders[i].CommandsList.Length;
for (int j = 0; j < counter; j++ )
{
description += "#"+pluginsHolders[i].CommandsList[j];
}
dataToSend.DataArr = new byte[description.Length];
/*char[] descriptionCh = description.ToCharArray();
for (int j = 0; j < description.Length; j++)
{
dataToSend.DataArr[j] = (byte)descriptionCh[i];
}*/
dataToSend.DataArr = RPCMArrayConverter.CharArrToByteArr(description.ToCharArray());
Logger.Instance.LogToConsole("Engine.HandleData: " + description);
Logger.Instance.LogToConsole("Engine.HandleData: " + new String(RPCMArrayConverter.ByteArrToCharArr(dataToSend.DataArr)));
byte[] dataBytes = NetworkDataParser.DataToBytes(dataToSend);
client.SendData(dataBytes);
}
}
}
private void DataSendRequiredHandler (object sender, EventArgs e)
{
RPCMData data = null;
try
{
Logger.Instance.LogToConsole("Engine.DataSendRequiredHandler");
data = e as RPCMData;
if (sender == null || e == null) return;
if (data.Client != null)
{
Logger.Instance.LogToConsole("Engine.DataSendRequiredHandler: Send Data To Client");
data.Client.SendData(NetworkDataParser.DataToBytes(data));
}
}
catch(ConnectionClosedException)
{
OnClientDisconnected(data.Client);
}
catch(Exception ex)
{
Logger.Instance.LogException(ex);
Logger.Instance.PopupErrorMessage(ex.Message);
}
}
private void WatchDogThreadProc()
{
try
{
Logger.Instance.LogToConsole("Engine.WatchDogThreadProc");
while(true)
{ Logger.Instance.LogToConsole("Engine.WatchDogThreadProc: Cycle");
Thread.Sleep(5000);
if (clientsAL == null) return;
Client[] clients = (Client[])clientsAL.ToArray(typeof(Client));
//foreach (Client client in clientsAL)
for (int i = 0; i < clients.Length ; i++)
{
try
{
RPCMData data = new RPCMData();
data.GUID = "00000000000000000000000000000000";
data.MessageType = (int)MessageTypes.Test;
data.DataArr = new byte[4]{(byte)'t',(byte)'e',(byte)'s',(byte)'t'};
clients[i].SendData(NetworkDataParser.DataToBytes(data));
Logger.Instance.LogToConsole("Engine.WatchDogThreadProc: Client " + clients[i].ToString() + " SendData");
}
catch(ConnectionClosedException/* ex*/)
{
//Logger.Instance.LogToConsole(ex.Message + " " + ex.ErrorCode.ToString());
OnClientDisconnected(clients[i]);
}
}
}
}
catch (ThreadInterruptedException)
{
}
catch (Exception ex)
{
Logger.Instance.LogException(ex);
Logger.Instance.PopupErrorMessage(ex.Message);
}
}
}
}

суббота, 28 августа 2010 г.

Часть 3: Система удаленного управления приложениями персонального компьютера с помощью мобильных устройств

1 Сервисы

Как уже говорилось выше, классы, реализующие сетевой сервис, должны имплементировать интерфейс RPCMNetworkService и реализовывать все его методы:
Initialize – инициализация сервиса до его запуску. Позволяет сервису показать диалоговое окно настройки параметров данного сервиса, а так же дать возможность сервису инициализировать внутренние параметры;
Start – запуск сервиса сервером;
Stop – остановка работы сервиса сервером;
GetName – получение имени сервиса для отображения его, например, в списке клиентов.
Также клиент должен реализовывать событие ClientConnected, возвращая в обработчик реализацию абстрактного класса Client.
Именование должно происходить следующим образом. Пространство имен сервиса должно называть RPCMNetworkServiceNamespace, а класс сервиса RPCMNetworkServiceInstance.
Так же в библиотеку сервиса должна входить реализация абстрактного класса Cient, возвращаемого в качестве аргумента, обработчику события сервиса ClientConnected. Объект этого класса является логической связью с подключившимся клиентом.
Реализация Client должна определять следующие методы:
SendData – позволяет послать данному клиенту массив байт;
CloseConnection – вызывается при желании сервера завершить соединение с клиентом, а так же при недоступности клиента, для освобождения занятых ресурсов;
GetService – получение ссылки на сервис, создавший клиента;
GetDescription – получение некоторого описания клиента (например, IP адрес в Wi-Fi / LAN сервисе)
Так же клиент должен реализовывать событие DataBytesReceived, возникающее при получении данных от подключенного клиента.

1.1 Wi-Fi / LAN

Реализация данного сервиса состоит из двух файлов LANService и LANClient являющихся реализациями соответствующих интерфейса и абстрактного класса. Работа с Wi – Fi осуществляется с помощью сокетов (socket) и асинхронных операций работы с ними. После запуска, сервис находится в постоянном ожидании подключения. Когда клиентское приложение подключается, сервер вызывает соответствующее событие, передавая в качестве аргумента объект класса LANClient, хранящий в себе соответствующий сокет соединения с клиентом и позволяющий отправлять и принимать данные от клиента.

1.2 Bluetooth

Данный сервис в настоящее время находится в разработке.

2 Реализация плагинов

Как говорилось выше, для реализации плагина, необходимо создать реализацию абстрактного класса RPCMPlugin, находящегося в rpcmsdk.dll. Он содержит следующие абстрактные методы:
GetGUID – возвращает строку из 32 симоволов (латиница), являющуюся уникальным идентификатором плагина. Для простоты и большой вероятности уникальности идентификатора лучше воспользоваться стандартными средствами генерации GUID в Visual Studio (меню "Tools" -> Create GUID, затем убрать все разделители).
GetName – возвращает строку, содержащую краткое имя плагина;
GetDescription – возвращает строку, содержащую описание возможностей и смысла команд плагина, а также его версию;
GetAbout – возвращает строку, содержащую информацию о разработчиках;
GetCommandsList – возвращает массив строк, являющихся одновременно и именами и передаваемыми идентификаторами команд;
DataReceivedHandler – обработчик получения данных со стороны сервера (через связку клиент – сервер – плагин). В качестве аргументов получает объекты типа Client, описывающий клиента, пославшего данные, и RPCMData, содержащий логическое представление посланных данных.
Также абстрактный класс содержит событие DataReceivedRequired и функцию вызова данного события OnDataSendRequired, с помощью которой плагин может посылать данные обратно клиенту. На данный момент реализована возможность посылки текстовых данных, например результата последней операции.
Как было сказано выше, класс и пространство имен должно иметь строгое именование. Реализация класса плагина должна называться RPCMPluginInstance и находиться в пространстве имен RPCMPluginNamespace.

2.1 WinampControl плагин

Данный плагин позволяет управлять некоторыми возможностями музыкального и видео проигрывателя WinAMP. Среди возможностей реализованных в плагине:
Ø Переключение на следующую и предыдущую песни
Ø Начать проигрывание
Ø Пауза и продолжение проигрывания
Ø Остановка проигрывания
Ø Увеличение и уменьшение громкости
Ø Перемотка текущей песни назад и вперед с интервалом 5 секунд
Данный плагин состоит из одного значимого файла WinampPlugin.h, также файла, предоставляемого разработчиками WinAMP для сторонних разработчиков и работы с проигрывателем wa_ipc.h.
Для отправки команды WinAMP, необходимо найти главное окно зарегистрированного приложения, затем, с помощью оконных сообщений отправить необходимые команды.
Результатом, отправляемым клиенту, является строка с указанием того, что желаемое действие было произведено.

2.2 Shutdown плагин

Данный плагин позволяет пользователю управлять различными режимами завершения работы компьютера, такими как:
Ø Выключение компьютера
Ø Перезагрузка компьютера
Ø Завершение сеанса пользователя
Ø Переход в спящий режим (если разрешено в настройках системы)
Проект плагина состоит из одного значимого файла – ShutdownPlugin.h, который является реализацией абстрактного класса RPCMPlugin и имеет соответсвующее именование и реализацию необходимых функций, основанных на стандартной функции WinAPI ExitWindowsEx. Следует заметить, что при завершении работы используется флаг, указывающий на закрытие программ в любом случае, даже если в них были не сохраненные изменения и они требуют подтверждения выхода.


3 Отладочная программа Wi-Fi/LAN сервиса

Для того чтобы проверить работоспособность сервера и сервиса Wi-Fi/LAN необходимо написать отладочную программу - клиента, выступающую, в роли, например, абстрактного мобильного устройства.
clip_image002
Рисунок 1. Отладочная программа – клиент

На рисунке выше приведено главное и единственное окно отладочной программы-клиента. Нет смысла вдаваться в подробности реализации данного приложения на уровне классов и их связи, так как оно не является частью разрабатываемой системы, было сделано только для личного использования и для того, чтобы показать пример работы системы, не имея реальных устройств.
Для того чтобы начать работу с приложением, необходимо предварительно запустить сервер. По умолчанию Wi-Fi/LAN сервис запускается на 55555 порту. Далее в поле отладочного приложения вводим IP адрес компьютера, на котором запущен сервер. На рисунке поле для адреса заполнено "127.0.0.1", это означает, что сервер запущен на той же машине, что и клиент. При указании такого адреса подключение к сети или наличие сетевой карты не обязательно. После ввода сетевого адреса и порта необходимо нажать кнопку "Connect" для соединения с сервером. После соединения (отдельного индикатора в окне программы нет, можно посмотреть на самом сервере), появляется возможность отправить серверу сообщение.
Главное окно приложения разбито на две части – первая, представляет пользователю формат сообщения (в данной реализации), то есть пользователь (разработчик) может представить, в каком виде данные передаются серверу. Все поля, кроме Data и Type закрыты для редактирования, потому что GUID определяется из полученных описаний плагинов, а длина данных из того, насколько заполнено текстовое поле, соответствующее данным. Так же пользователю предоставляется возможность произвольно заполнять поле Data и выбирать тип посылаемого сообщения. Для того чтобы получить список доступных плагинов необходимо, после подключения к серверу, выбрать тип сообщения PluginsDescriptionRequired и нажать кнопку Send (отправка). После этого заполняется вторая область окна.
Вторая область предназначена для работы с плагинами и представляет, как бы, виртуальный экран мобильного устройства. После получения информации о плагинах, заполняется выпадающий список с именами. При выборе имени в выпадающем списке, справа, в раскрытом списке, появляются доступные для конкретного плагина команды. А под списком плагинов появляется описание плагина. Если сделать двойной щелчок по команде плагина, то все поля сообщения заполнятся соответствующим образом и, если установлен флаг "Direct Send", сразу будут отправлены серверу.
Если плагин возвращает какую-то информацию (в текущей реализации – текстовую), то она появляется в окне результата. Примером плагина, возвращающего текстовую информацию, является WinampControl плагин.
Разработано данное приложение, с применением библиотеки rpmsdk.dll, использование функций и классов которой во многом упрощает процесс разработки.
Описанное выше приложение позволяет проверить функционирование сервиса Wi-Fi\LAN и корректность передачи данных, а так же корректную работу сервера, обработку сообщений и отправку информации о плагинах, передачу данных самими плагинами. Так же, данное приложение является наглядным пособием разработчику, позволяющим показать работу системы и часть ее внутреннего устройства, такого как формат передачи данных.


4 Заключение

В данное время, беспроводные технологии, такие как Wi-Fi и Bluetooth все больше входят в нашу жизнь, позволяя связывать всю, окружающую человека электронику, в одну логическую сеть, начиная с мобильного телефона и заканчивая фотоаппаратом, предоставляя несчетное число различных возможностей. Одна из них – управление приложениями на компьютере с помощью мобильных устройств, используя в качестве среды передачи данных перечисленные выше технологии. Однако, приложения, являющие собой решения данной задачи, весьма ограничены функционально из-за недостаточной расширяемости и поддержки малого количества платформ мобильных устройств. Целью данной работы было проектирование системы, лишенной перечисленных выше недостатков и реализация: серверной части, Wi-Fi\LAN сервиса и плагинов управления проигрывателем WinAMP и завершения работы компьютера. Платформой для разработки серверной части была выбрана распространенная на данный момент и перспективная платформа Microsoft .NET Framework, предоставляющая разработчику большие возможности.
В результате данной работы была спроектирована и реализована система, абстрагированная от среды передачи данных и модульная, позволяющая разработчикам создавать собственные расширения, покрывая недостающую функциональность и обеспечивая поддержку новых приложений, а так же позволяя разрабатывать модули работы с появляющимися новыми или редкими средами передачи данных. Работоспособность системы была проверена, найденные недостатки устранены.
Так же, в рамках данной работы, было разработано тестовое приложение, демонстрирующее работу системы и являющееся в какой-то мере, обучающим, показывающим формат сообщений, которыми обмениваются сервер и клиент.
В дальнейшем, планируется добавление новой функциональности, такой, как обмен сервера и клиента сообщениями в формате XML, реализация Bluetooth сервиса, возможность возврата плагином не только текстовой информации, но и информации других типов, например, изображений, реализация "обратного сообщения", то есть управление мобильным устройством, например КПК, с помощью компьютера.

Часть 2: Система удаленного управления приложениями персонального компьютера с помощью мобильных устройств

1 Серверное приложение

clip_image002
Рисунок 1. Диаграмма связи классов серверного приложения
Рассмотрим более подробно исходные классы серверного приложения и связи между ними.
В данном приложении была реализована популярная сейчас модель программирования Model – View – Controller, когда логика приложения и его отображение разделены в программном коде, для большей расширяемости, удобстве внесения изменений, портировании. Так же было решено взаимодействие между Model и View-Controller сделать только в двух классах (Engine и UIEngine), являющихся посредниками между остальными классами, реализация взаимодействия была сделана в стиле данного языка программирования и его средствами – событиями и обработчиками событий.
Классы:
Ø ProgramStart
Стартовым классом программы является ProgramStart. Он запускает основной цикл обработки сообщений системы приложением и передает управление классу UIEngine
Ø UIEngine
UIEngine – так же как и класс Engine, сделан с применением паттерна проектирования Singleton, позволяющего получать доступ к классу из любой части кода без явного создания и хранения на этот класс ссылки через поле Instance, при обращении к которому происходит неявное создание объекта класса. Этот класс отвечает за управлениями окнами приложения и обработкой части событий, происходящих на этих формах, таких как, например, нажатие кнопки.
Данный класс содержит открытый метод Run, вызываемый в предыдущем классе, при запуске программы. В этом методе происходит создание основных диалоговых окон приложения. Они создаются только один раз, далее показываются или скрываются в зависимости от действий пользователя.
При вызове конструктора метода (при неявном создании), происходит добавление обработчиков событий класса Engine, описанного ниже. Перечислим закрытые методы обработчики:
· engine_ServerStarted – обработка события запуска сервера.
· engine_ServerStopped – обработка события остановки сервера. Происходит очистка всех визуальных списков на окнах приложения.
· engine_ClientConnected – обработка события подключения нового клиента. В этом методе происходит добавление клиента в список.
· engine_PluginsLoaded – обработка события окончания загрузки плагинов сервером. В данном методе происходит добавление информации о доступных плагинах в список соответствующего окна.
· engine_ClientDisconnected – обработка события обнаружения отключения клиента. Происходит удаление данного клиента из списка.
Так же в данном классе определен закрытый метод mainFormToolBar_ButtonClick, реализующий обработку нажатия на кнопку главного окна приложения и соответствующие действия.
Ø MainForm
clip_image004
Рисунок 2. Главное окно приложения
Этот класс представляет собой главную форму приложения, представляющую собой панель, предоставляющую пользователю возможность запускать сервер, открывать другие окна приложения, сворачивать его и закрывать. Событие нажатие на любую из кнопок переадресовывается UIEngine в функцию mainFormToolBar_ButtonClick с соответствующим аргументом – классом нажатой кнопки.
Так же этот класс содержит в себе объект класса NotifyIcon, отвечающего за отображение значка в системном лотке. Если сервер не запущен, то значок белый, а если запущен – зеленый. По двойному щелчку по значку, все окна приложения появляются или скрываются, в зависимости от текущего состояния.
clip_image006
Рисунок 3. Значок сервера в системном лотке (сервер не запущен)

clip_image008
Рисунок 4. Значок сервера в системном лотке (сервер запущен)
Ø ClientsForm
Класс, отвечающий за форму, отображающую текущих подключенных пользователей. При подключении нового пользователя, он добавляется в список, отображающий название сервиса, обслуживающего пользователя и некоторое описание, предоставляемое сервисом (например, IP адрес для Wi-Fi/LAN сервиса).
Все пространство данного окна занимает список clientsListView, имеющий модификатор internal, то есть доступный для изменения внутри сборки (Assembly). Это необходимо, так как добавление и удаление клиентов в список происходит в классе UIEngine.
clip_image010
Рисунок 5. Окно списка подключенных клиентов (ClientsForm)
Ø PluginsForm
Класс, отвечающий за отображению списка доступных плагинов, который обновляется при старте сервера. Большую часть пространства данного окна занимает список pluginsListView, имеющий модификатор internal, то есть доступный для изменения внутри сборки (Assembly). Это необходимо, так как добавление и удаление плагинов в список происходит в классе UIEngine. В этом списке находится название плагина, его уникальный идентификатор, а так же список команд.
Так же в окне расположены два текстовых поля, отображающих информацию о назначении выбранного в списке плагина и информацию от разработчиков.
clip_image012
Рисунок 6. Окно списка загруженных плагинов (PluginsForm)
Ø HelpForm
Окно с логотипом приложения и упоминанием разработчиков. Никакой специальной функциональности и не несет.
clip_image014

Рисунок 7. Окно информации о разработчиков (HelpForm)
Ø Engine
Класс, являющийся "двигателем" приложения, обеспечивающий всю логику работы, загрузку модулей. Он связан с UIEngine событиями: запуска и остановки сервера, подключения и отключения клиентов, события завершения загрузки плагинов. Список событий:
· ServerStarted – событие, оповещающее, что запуск сервера завершился;
· ServerStoped – событие, оповещающее, что остановка сервера завершилась;
· PluginsLoaded – событие, оповещающее, что загрузка плагинов сервером завершена;
· ClientConnected – событие, оповещающее о подключении клиента;
· ClientDisconnected – событие, оповещающее об отключении клиента;
Следует сказать, что данный класс имеет поле Plugins, типа RPCMPluginHolder[] (массив), предоставляющее другим классам возможность получать информацию о загруженных плагинах.
Еще одной особенностью данного класса является то, что при старте сервера запускается поток, который каждые 5 секунд отправляет сообщение типа Test всем подключенным клиентам, отслеживая при этом исключение типа ConnectionClosedException из rpcmsdk.dll, получая которое, вызывает событие ClientDisconnected и удаляет клиента из списка клиентов (внтуреннего).
Ø ClientListViewItem
Класс, хранящий в себе указатель на объект, описывающий клиента, чтобы можно было при отключении данного клиента, найти и удалить его в списке
Ø RPCMPluginHolder – класс, являющийся "оберткой" класса типа RPCMPlugin, упрощая работу с данным классом. Значимого применения в данной реализации не имеет, но, в последствии, должен будет реализовывать логическую обработку данных, выполняя роль прослойки между сервером и плагином.

2 Библиотека rpcmsdk.dll

clip_image016
Рисунок 8. Диаграмма связи классов библиотеки rpcmsdk
Данная библиотека является необходимой и разделяемой между основным приложением, сервисами и плагинами. Она так же является необходимой при разработке дополнительных модулей. Рассмотрим, какие классы и интерфейсы в нее входят.
Абстрактные классы:
Ø RPCMPlugin
Интерфейс, описывающий набор методов, которые должен иметь плагин.
Ø RPCMNetworkService
Абстрактный класс, описывающий набор методов, которые должен иметь сервис, а также событие ClientConnected, возникающее в случае подключения нового клиента и передающее обработчику реализацию абстрактного класса Client.
Ø Client
Абстрактный класс, описывающий набор методов, которые должен иметь объект, создаваемый сервисом при подключении нового клиента, а также событие DataBytesReceived типа DataBytesReceivedHandler, оповещающее о получении данных от данного клиента.
Классы:
Ø RPCMData
Класс, являющейся переносчиком логической информации от плагина к сервису, содержит некоторую, необходимую для общения клиента и сервера, информацию, например, уникальный идентификатор плагина.
Ø Logger
Разделяемый класс, написанный, для унификации вывода отладочных сообщений и записи в файл отладочной информации.
Ø RPCMArrayConverter
В рамках поставленной задачи не редко приходится конвертировать массивы типа char[] в byte[] и наоборот, для этой цели был написан данный класс.
Ø NetworkDataParser
При разработке системы была принята концепция независимости среды передачи данных от логического наполнения этих данных. Данный класс является преобразователем объекта, хранящего некоторую логическую информацию о команде клиентскому приложению в массив байт, который должен быть передан через среду передачи данных (с помощью сервиса) и наоборот, преобразование массива байт, полученного от клиентского приложения в объект логических данных. Это, так же, позволяет изменять формат передачи данных, без изменений в других частях кода. К примеру, сейчас реализован фиксированный формат данных, приведенный на рисунке ниже. Планируется переход от данного формата к передаче данных в XML. Для этого необходимо будет изменить только данный класс.
Ø ConnectionClosedException
Класс исключения, которое должен посылать сервис при отключении клиента и невозможности послать ему сообщение.
Так же в состав библиотеки входит перечисление MessageTypes, в котором содержатся типы возможных посылаемых сообщений и тип делегата DataBytesReceivedHandler.

3 Формат передачи данных и типы сообщений

В данном разделе рассмотрим более подробно реализованный на данный момент формат сообщения, а также типы сообщений, которыми обмениваются клиент и сервер.
clip_image018
Рисунок 9. Формат сообщения
На рисунке слева указано имя поля, справа длина в байтах.
Ø GUID – 32 байта, уникальный идентификатора плагина, которому посылается сообщение от клиента или от которого было послано сообщение клиенту. Данное поле может также не использоваться в некоторых случаях;
Ø Message Type – 2 байта, тип сообщения. Перечислим все типы посылаемых сообщений, реализованные на данный момент:
· Test – тип сообщения для проверки на доступность клиента. Клиент может отсылать или не отсылать ответное сообщение, но если отсылает обратное сообщение, то только типа Test
· PluginDescriptionRequired – запрос описания всех плагинов (сообщение от клиента). В данном сообщении поле GUID игнорируется
· PluginDescription – содержит информацию о плагине следующего формата. GUID – идентификатор, а в поле Data идет символьная строка (ASCII и латиница) вида "Имя – разделитель – Описание – разделитель – Список команд через разделитель". На момент текущей реализации разделителем является символ '#'. В дальнейшем планируется унифицировать разбор сообщений данного типа, вынеся процедуру разбора в rpcmsdk.dll, так же планируется сделать поддержку Unicode.
· Command – содержит команду, клиентом посланную плагину. Поле GUID содержит идентификатор плагина. В данной реализации сравнение GUID плагина возложено сами на плагины, чтобы дать возможность писать системные плагины, такие как, например, NetworkDebugPlugin – отображающий все пришедшиесообщения.
· PluginResultInfoText – возвращает некоторую текстовую информацию от плагина клиенту (как, например, WinampControl Plugin, см. ниже). В дальнейшем планируется реализовать другие типы возвращаемой информации, например графические изображения.
Ø Length – 4 байта – указание размера поля Data, для избегания ошибок возврата неверного размера;
Ø Data - … - поле для посылаемой информации, зависящее от типа сообщения.

Часть 1: Система удаленного управления приложениями персонального компьютера с помощью мобильных устройств.

1. Введение. Актуальность проблемы.

Стремительно развивающиеся технологии беспроводной передачи данных, такие как Bluetooth и Wi-Fi открывают для пользователей все больше возможностей. Сейчас практически все мобильные телефоны средней ценовой категорией и смартфоны оснащены Bluetooth передатчиками, а современные ноутбуки и карманные персональные компьютеры (КПК) оснащены Wi-Fi передатчиками, что открывает новую нишу рынка для приложений, использующих перечисленные выше технологии.
Остановимся подробнее на классе приложений, позволяющих связывать мобильное устройство и персональный компьютер между собой. Сейчас на рынке существует не большое количество приложений такого рода, отличающихся между собой функциональностью, расширяемостью, типами поддерживаемых устройств. Проведем краткий обзор нескольких приложений.

1.1 Обзор программ для управления компьютером при помощи мобильных устройств

Control Freak – приложение для смартфонов на платформе Symbian Series 60. Первоначально, программа была предназначена для управления известным медиаплеером Winamp с помощью смартфонов Series60, однако разработчики включили в более поздние версии небольшой модуль для отображения экрана компьютера, переросший затем в прекрасное средство управления удалённым рабочим столом. А поскольку программа обладает приятной внешностью и дружелюбным поведением, да и к тому же регулярно обновляется, можно рассчитывать на то, что в следующих версиях возможно будет совершать любые действия на компьютере с помощью телефона.
Возможности:
— Полное управление медиаплеером winamp, включая медиа-библиотеку и редактор списка воспроизведения.
— Управление мышью/курсорными клавишами (доступны левая кнопка мыши, Alt+Tab, Enter, Esc и ввод произвольного текста).
— Управление работой компьютера (Выключение, перезагрузка, режим ожидания, спящий режим).
— При входящем звонке уменьшает громкость/приостанавливает воспроизведение.
Из плюсов помимо интерфейса можно отметить простоту использования, лёгкость настройки и небольшие размеры.
Недостатком является то, что серверная часть приложения реализована в виде расширения Winamp.
Puppet Master – приложения для смартфонов на платформе Symbian и телефонов с поддержкой Bluetooth или GPRS.
Плюсами данной программы является ее переносимость на большое число телефонов, возможность передачи данных через GPRS и расширяемость управления различными приложениями с помощью разработки дополнительных модулей.
Минусом является не выделяющийся красотой интерфейс приложения (из-за поддержки расширяемости).
Возможности:
— Управление Winamp, Windows media player, iTunes, Outlook, PowerPoint с помощью меню.
— Управление мышью (доступны левая и правая кнопки).
— Дополнение сторонними плагинами (Язык Visual Basic).
— Набор действий на события (начало и конец звонка, соединение и разъединение телефона с ПК)
Bluetooth Remote Control – приложение для телефонов, поддерживающих расширение JSR-82 (Bluetooth API).
Возможности:
— Управление WinAMP, PowerPoint , iTunes, Windows Media Player, мышь
— Возможность просмотра рабочего стола на телефоне
— Написание собственных скриптов управления программами (посылка сообщений нажатия клавиш)
Недостатки:
Расширяемости недостаточно, так как множество функций приложения может быть недоступно только по нажатию клавиш (эмуляция).
Zerama Remote Version – приложение для КПК на платформах Pocket PC 2000, 2002, 2003 &2003 SE с поддержкой Bluetooth и Wi-Fi.
Возможности:
— Управление Windows Media Player 9 / 10.
Недостатки:
— Нет расширяемости.
Среди рассмотренных выше приложений можно выделить следующие недостатки:
- Недостаточная расширяемость
- Поддержка только одного типа мобильных устройств (за редким исключением)

1.2 Постановка задачи

В данной работе исследуется возможность написания приложения, лишенного приведенных выше недостатков, расширяемого и поддерживающего работу с клиентскими приложениями, портированными на разные типы мобильных устройств, такие как КПК на платформе WinCE с поддержкой .NET Compact Framework, мобильный телефон с поддержкой JSR-82, смартфон.


2 Архитектура проекта

2.1 Система

clip_image002
Рисунок 1. Общая архитектура системы
На Рисунке № 1 представлена глобальная архитектура системы и то, с помощью каких технологий управляющие устройства соединяются и обмениваются данными с серверным приложением. В качестве управляющего устройства могут выступать: ноутбук или другой компьютер, телефон, КПК, смартфон, - с установленными клиентскими приложениями и доступом к перечисленным выше средам передачи данных. В свою очередь, серверное приложение конвертирует полученные данные некоторого формата во внутренний тип данных и передает расширениям – плагинам, в которых реализована некоторая функциональность, например, работа с проигрывателем мультимедийных файлов или операционной системой.
Основной упор, при построении такой системы, делается на расширяемость, модульность, абстрагирование от среды передачи данных. Эти вопросы будут более подробно освещены в следующих разделах.

2.2 Используемые технологии

2.3 Bluetooth

Bluetooth — радио-технология ближнего действия, призванная заменить провода, соединяющие переносные и стационарные электронные устройства. Bluetooth разработан для работы в зашумлённых (радио-сигналами) средах. Модули Bluetooth работают в диапазоне частот ISM (Industry, Science and Medicine — промышленный, научный и медицинский; 2400—2483.5 MHz), который в большинстве стран является свободным от лицензирования. Исключение составляют Испания, Франция и Япония, где диапазон частот, разрешённых для Bluetooth, гораздо меньше. Поэтому устройства, произведённые для этих стран, не будут работать с другими устройствами. Хотя с этими государствами ведутся переговоры, и, возможно, в ближайшем будущем, все Bluetooth устройства будут совместимы.
Пропускная способность Bluetooth составляет 723.2 кб/с. Также через Bluetooth можно передавать до 3 аудио-каналов. В настоящее время расстояние, на которое Bluetooth способен передавать данные, составляет от 10 (в большинстве случаев) до 100 метров. Передача возможна даже через объекты (стены и др.), если, конечно, они не экранированы. Энергия, потребляемая модулем Bluetooth, не должна превышать 10 мВт.
Соединение может происходить не только по принципу «точка — точка», но и «точка — много точек». В этом случае устройство, к которому подключаются, называется master, а те, которые подключаются — slave. Master-устройство управляет частотной и пакетной синхронизацией подключённых к нему устройств. К одному master может быть подключено до 7 активных (активно обменивающихся данными) slave, а также множество неактивных, ждущих освобождения канала. Такая структура называется pico-net. В одной pico-net может быть только один master, но каждый slave может быть master в других pico-net, образуя таким образом scatter-net. В scatter-net устройство может быть не только одновременно master и slave для разных pico-net, но и slave для разных pico-net. В случае же необходимости slave-устройство может становится master в этой же pico-net (естественно, что при этом старый master становится slave). Разные pico-net одной scatter-net должны работать на различных частотах.
Для избежания помех и защиты от перехвата информации используется псевдослучайный механизм переключения частот (1600 скачков в секунду). По сравнению с другими радио-технологиями, действующими на той же частоте, Bluetooth переключает частоты быстрее и использует более короткие пакеты данных.
Применяется до трех уровней защиты (в зависимости от поставленной задачи: 1) без специальной защиты; 2) доступ только к зарегистрированным устройствам, включая ввод пароля пользователем; 3) защита информации ключом эффективной длины от 8 до 128 бит (что позволяет устанавливать стойкость результирующего шифрования в соответствии с законодательством каждой отдельной страны: в некоторых странах запрещено использование сильной криптографии) при передаче в одну или обе стороны.
Каждое устройство имеет уникальный 48-битный сетевой адрес, совместимый с форматом стандарта локальных сетей IEEE 802.11х. Первые 24 бита определяют компанию-производителя чипа.
Для связи с Bluetooth устройствами сначала происходит их поиск (device discovery). Для этого посылается запрос, и ответ на него зависит не только от наличия в радиусе связи активных Bluetooth устройств, но и от режима в котором находятся эти устройства.
Discoverable Mode. Находящиеся в этом режиме устройства всегда отвечают на все полученные ими запросы.
Limited discoverable mode. В этом режиме находятся устройства которые могут отвечать на запросы только ограниченное время, или должны отвечать только при соблюдении определённых условий.
Non-discoverable mode. Находящиеся в этом режиме устройства, как видно из названия режима, не отвечают на новые запросы.
Но даже если удаётся обнаружить устройство, оно может быть в двух режимах: connectable или non-connectable. В non-connectable режиме устройство не позволяет настроить некоторые важные параметры соединения, и, таким образом, оно хоть и может быть обнаружено, обмениваться данными с ним не удастся. Если устройство находится в connectable режиме, то на этом этапе Bluetooth устройства «договариваются» между собой о физических параметрах соединения.
Одно из преимуществ Bluetooth перед конкурирующими технологиями в том, что эта технология не подлежит платному лицензированию и ее использование не требует выплаты каких-либо лицензионных отчислений (хотя и требует подписания бесплатного соглашения).

2.4 Wi-Fi

Wi-Fi (произносится как [вай-фай]), сокр. от англ. Wireless Fidelity — протокол и стандарт на оборудование для широкополосной радиосвязи, предназначенной для организации локальных беспроводных сетей Wireless LAN. Установка таких сетей рекомендуется там, где развертывание кабельной системы невозможно или экономически нецелесообразно. Благодаря функции роуминга между точками доступа пользователи могут перемещаться по территории покрытия сети Wi-Fi без разрыва соединения.
Обычно схема Wi-Fi сети содержит не менее одной точки доступа (AP, от англ. access point) и не менее одного клиента. Точка доступа передает свой SSID (англ. Service Set IDentifier, Network name — идентификатор сети, сетевое имя) с помощью специальных пакетов, называемых сигнальными пакетами, передающихся каждые 100 мс. Сигнальные пакеты передаются на скорости 1 Mбит/с и обладают малым размером, поэтому они не влияют на характеристики сети. Так как 1 Mбит/с — наименьшая скорость передачи данных для Wi-Fi, то клиент, получающий сигнальные пакеты, может быть уверен, что сможет соединиться на скорости не менее, чем 1 Mбит/с. Зная параметры сети (то есть SSID), клиент может выяснить, возможно ли подключение к данной точке доступа. Программа, встроенная в Wi-Fi карту клиента, также может влиять на подключение. При попадании в зону действия двух точек доступа с идентичными SSID программа может выбрать между ними на основании данных об уровне сигнала. Стандарт Wi-Fi дает клиенту полную свободу при выборе критериев для соединения и роуминга. В этом преимущество Wi-Fi, хотя оно означает, что один из адаптеров может выполнять эти действия гораздо лучше другого. Операционные системы семейства Windows, начиная с Windows XP, содержат функцию, называемую zero configuration, которая показывает пользователю все доступные сети и позволяет переключаться между ними «на лету». Новейшая функция от Microsoft, названная SoftMAC не будет зависеть от встроенного ПО адаптера. Это означает, что роуминг будет полностью контролироваться операционной системой. Wi-Fi передаёт данные по воздуху, поэтому он обладает свойствами, сходными с некоммутируемой ethernet-сетью, и для него могут возникать такие же проблемы, как при работе с некоммутируемыми ethernet сетями.

2.5 Microsoft .NET

.NET (произносится дот-нет) — программная технология, предложенная фирмой Microsoft в качестве платформы для создания как обычных программ, так и веб-приложений. Во многом является развитием идей и принципов, заложенных в технологии Java.
Одной из основных идей .NET является совместимость различных служб, написанных на разных языках. Служба, написанная на C++ для .NET, может обратиться к методу класса из библиотеки, написанной на Delphi; на C# можно написать класс, наследующий от класса, написанного на Visual Basic .NET, а исключение, выброшенное методом, написанным на C#, может быть поймано и обработано в Delphi. Каждая библиотека (сборка) в .NET имеет сведения о своей версии, что позволяет устранить возможные конфликты между разными версиями сборок.
.NET — кроссплатформенная технология, однако в настоящее время существует реализация для платформы Microsoft Windows, FreeBSD (от Microsoft) и ограниченный вариант технологии для ОС Linux в рамках свободных проектов Mono, DotGNU.
К сожалению, .NET является патентованной технологией фирмы Microsoft, что является препятствием для её распространения на другие платформы (относительно проекта Mono — Microsoft однозначно высказалась о нелигитимности данного проекта).
Хотелось бы отметить, что защита авторских прав относится к созданию сред исполнения (CLR — Common Language Runtime) для программ .NET. Компиляторы для .NET выпускаются множеством фирм для различных языков свободно. Множество используемых языков является несомненным преимуществом технологии .NET по сравнению с Java.
.NET делится на две основные части — среда выполнения (по сути виртуальная машина) и инструментарий разработки.
Среды разработки .NET-приложений: Visual Studio .NET (C++, C#, J#), SharpDevelop, Eclipse, Borland Developer Studio (Delphi, C#) и т. д. Приложения также можно разрабатывать в текстовом редакторе и использовать консольный компилятор.
Так же как и технология Java, среда разработки .NET создаёт байт-код, предназначенный для исполнения виртуальной машиной. Входной язык этой машины в .NET называется MSIL (Microsoft Intermediate Language) или просто IL. Применение байт-кода позволяет получить кроссплатформенность на уровне скомпилированного проекта (в терминах .NET: сборка), а не на уровне исходного текста, как, например, в С. Перед запуском сборки в среде исполнения (CLR) байт-код преобразуется встроенным в среду JIT-компилятором (just in time, компиляция на лету) в машинные коды целевого процессора.
Следует заметить, что в данной работе ядро приложения сервера написано на языке программирования C#, а плагины на managed С++ .

2.6 Архитектура серверного приложения

clip_image004
Рисунок 2. Общая архитектура серверного приложения

Остановимся более подробно на общей архитектуре и принципах работы серверного приложения. Серверное приложение состоит из ядра, то есть, самого исполняемого файла, а функциональность сервера обеспечивается плагинами и сервисами. Так же для корректной работы сервера, плагинов и сервисов необходимо, чтобы в корневой папке программы или в папке %WINDOWS%\system32 находился файл библиотеки "rpcmsdk.dll".
Сервис – модуль, являющийся библиотекой классов, скомпилированной под платформу .NET Framework v 1.1, обеспечивающий доступ к среде передачи данных. Он должен наследовать соответствующий интерфейс, находящийся в библиотеке rpcmsdk.dll, а так же иметь строго заданное именование классов, о чем будет сказано позже.
Плагин – модуль, являющийся библиотекой классов, скомпилированной под платформу .NET Framework v 1.1, обеспечивающий взаимодействие сервера с управляемыми приложениями. Он должен наследовать соответствующий интерфейс, находящийся в библиотеке rpcmsdk.dll, а так же иметь строго заданное именование классов, о чем будет сказано позже.
После запуска, сервер загружает все плагины, находящиеся в папке plugins, и сервисы, находящиеся в папке services, если они корректного формата, они инициализируются и начинают взаимодействие, иначе, ошибка выдается пользователю и сохраняется в файле "errors.log".