В этой теме размещаются сообщения и обсуждение использования SimConnect для получения событий FSX — глобальных, связанных с пользовательским самолетом и других.
Для начинающих!
========================
Записки по API функциям SimConnect.
После формирования программы с установкой функций открытия и завершения сеанса связи SimConnect-FSX, встает вопрос получения извещений о событиях в FSX. Без этой информации невозможно организовать управляющие воздействия, а значит нельзя влиять на логику работы самого FSX, траффика, погоды, самолетов, их оборудования и систем.
Начнем с получения извещений о системных событиях.
Системные события FSX — это события, связанные с общими действиями и обстановкой в FSX. Например, запуск и выключение FSX (SimStart, SimStop) и пользовательского самолета (AircraftLoaded), загрузка полета, запись полета, активация и деактивация плана полета (FlightPlan), крушение (Crashed) и другие события. SimConnect позволяет получить доступ к системным событиям и организовать реагирование на них.
Перечень системных событий, доступных для SinConnect, приведен в SDK описании API функции SimConnect_SubscribeToSystemEvent (см. скрин).
Для включения, изменения режима включения и выключения извещений о системных событиях используются следующие три функции:
SimConnect_SubscribeToSystemEvent
SimConnect_SetSystemEventState
SimConnect_UnsubscribeFromSystemEvent
Для получения же самого извещения о системном событии и его обработки надо использовать функцию обратной связи SimConnect_CallDispatch, в которой указать имя пользовательской функции DispatchProc, в которой и производится обработка событий. Например:
CALLBACK ShtDispatchProcReadTXT – пользовательская функция извещения о событии, созданная на основе API функции DispatchProc.
В свою очередь для работы пользовательской функции следует применять перечисление SIMCONNECT_RECV_ID_EVENT и структуру SIMCONNECT_RECV_EVENT, которые рассматриваются в описании перечислений и структур.
Сообщение отредактировал dmi-shef: 08 September 2013 — 14:10
========================
Продолжение записок по API функциям SimConnect SDK, начало см. пост #29 этой темы http://www.avsim.su/…0#entry2279836.
Описание API функций системных событий.
Подключаем наш скомпилированный файл к FSX через SimConnect (как это делается, я рассказал в первой части записок, приложенных к посту #26 http://www.avsim.su/forum/topic/126952-simconnect/page__st__20#entry2276637)
Запускаем FSX.
С началом загрузки окна главного меню открывается консольное окно с сообщением об установлении связи SimConnect-FSX (сработала функция открытия сеанса связи). После окончания загрузки окна главного меню FSX в консольном окне появится сообщение о первом системном событии — SIM. Оно означает, что FSX запущен.
Прикрепленные изображения
Сообщение отредактировал dmi-shef: 26 November 2012 — 13:38
========================
Продолжение записок по API функциям SimConnect SDK, начало см. пост #29 этой темы http://www.avsim.su/…0#entry2279836.
Описание API функций системных событий.
Выбираем режим свободного полета, самолет, аэродром и время начала сцены. Запускаем свободный полет.
После загрузки в консольном окне появятся сообщения об старте FSX, т.е. загрузке свободного полета и второе сообщение о загрузке FSX.
При закрытии FSX будут выданы сообщения об остановке симулятора и повторное сообщение SIM.
Таким образом, информация о системных событиях FSX получена нашей программой. Осталось распорядиться ей должным образом.
Прикрепленные изображения
Сообщение отредактировал dmi-shef: 26 November 2012 — 13:35
========================
Продолжение записок по API функциям SimConnect SDK, начало см. пост #29 этой темы http://www.avsim.su/…0#entry2279836.
Описание API функций системных событий.
SimConnect_SubscribeToSystemEvent
Эта функция используется для постоянного включения извещений клиента о системных событиях. Т.е. при использование данной функции извещения о системных событиях будут поступать клиенту постоянно.
Синтаксис:
HRESULT SimConnect_SubscribeToSystemEvent(
HANDLE hSimConnect,
SIMCONNECT_CLIENT_EVENT_ID EventID,
const char* SystemEventName
);
Параметры функции:
hSimConnect – указатель на дескриптор объекта SimConnect (т.е. используется объект SimConnect);
EventID — специфический идентификатор клиента;
SystemEventName – строковое имя системного события. Если иное не указано, извещение о системном событии возвращается в структуру функции SINCONNECT_RECV_EVENT.
Возвращаемая переменная:
Функция возвращает HRESULT. Возможные значения переменной: S_OK, если функция завершилась успешно, E_FALL – если функция не выполнена.
Примечания.
Для временного прекращения извещений о системном событии применяется API функция SimConnect_SetSystemEventState.
Для полного прекращения извещений о системном событии применяется функция SimConnect_UnsubscribeFromSystemEvent.
========================
Продолжение записок по API функциям SimConnect SDK, начало см. пост #29 этой темы http://www.avsim.su/…0#entry2279836.
Описание API функций системных событий.
SimConnect_SetSystemEventState
Эта функция используется для временного включения извещений клиенту о системных событиях.
Синтаксис:
HRESULT SimConnect_SetSystemEventState(
HANDLE hSimConnect,
SIMCONNECT_CLIENT_EVENT_ID EventID,
SIMCONNECT_STATE dwState
);
Параметры функции:
hSimConnect – указатель на дескриптор объекта SimConnect (т.е. используется объект SimConnect);
EventID – специфический идентификатор системного события;
dwState – два слова (SIMCONNECT_STATE_OFF и SIMCONNECT_STATE_ON), устанавливающие режим передачи извещений клиенту о системном событии. Эти слова являются параметром функции SIMCONNECT_STATE, которая устанавливает момент включения и выключения извещений о системном событии.
Возвращаемая переменная:
Функция возвращает HRESULT. Возможные значения переменной: S_OK, если функция завершилась успешно, E_FALL – если функция не выполнена.
Примечание.
Если эта функция не вызвана, то по умолчанию устанавливается режим постоянного вызова извещений о системном событии. Этим она отличается от функций установления статуса других, несистемных событий, у которых отсутствие функции по умолчанию приводит к отсутсвию извещений о событии.
========================
Продолжение записок по API функциям SimConnect SDK, начало см. пост #29 этой темы http://www.avsim.su/…0#entry2279836.
Описание API функций системных событий.
SimConnect_UnsubscribeFromSystemEvent
Эта функция используется для выключения извещений клиента о системных событиях.
Синтаксис:
HRESULT SimConnect_UnsubscribeFromSystemEvent(
HANDLE hSimConnect,
SIMCONNECT_CLIENT_EVENT_ID EventID
);
Параметры функции:
hSimConnect – указатель на дескриптор объекта SimConnect (т.е. используется объект SimConnect);
EventID – специфический идентификатор системного события.
Возвращаемая переменная:
Функция возвращает HRESULT. Возможные значения переменной: S_OK, если функция завершилась успешно, E_FALL – если функция не выполнена.
Примечание.
На количество системных событий, о которых одновременно сообщается клиенту, ограничений нет. Однако для повышения производительности лучше применять функцию SimConnect_UnsubscribeFromSystemEvent и выключать извещения о системных событиях, когда надобность в них миновала.
========================
Продолжение записок по API функциям SimConnect SDK, начало см. пост #29 этой темы http://www.avsim.su/…0#entry2279836.
Описание API функций системных событий.
API функции можно помещать или в главную функцию, или в пользовательские функции программы.
Приведу пример получения системных событий. Он сделан на основе примеров SDK исключительно для иллюстрации возможностей API функций, а не для показа правильной организации программы.
#include <windows.h>
. .
#include «SimConnect.h»
int quit = 0;
HRESULT ShtHr;
HANDLE hSimConnect = NULL;
// Описание событий
static enum EVENT_ID {
EVENT_SHT_SIM,
EVENT_SHT_SIM_START,
EVENT_SHT_SIM_STOP,
};
// === Пользовательская функция обратной связи, сообщает о событиях в FSX ===============
void CALLBACK ShtDispatchProcReadTXT(SIMCONNECT_RECV* pData, DWORD cbData, void *pContext)
{
int b = 0;
switch(pData->dwID) // Доступ к атрибуту через указатель pData на объект dwID, т.е. объект с ID, указанным ниже
{
case SIMCONNECT_RECV_ID_EVENT:
{
SIMCONNECT_RECV_EVENT *evt = (SIMCONNECT_RECV_EVENT*)pData;
switch(evt->uEventID) // Доступ к атрибуту evt через указатель на объект uEventID
{
case EVENT_SHT_SIM: // Здесь указатель на ID -> EVENT_SHT_SIM
std::cout << «nEvent EVENT_SHT_SIM» << evt->dwData;
break;
case EVENT_SHT_SIM_START: // Здесь указатель на ID -> EVENT_SHT_SIM_START
std::cout << «nEvent EVENT_SHT_SIM_START» << evt->dwData;
break;
case EVENT_SHT_SIM_STOP: // Здесь указатель на ID -> EVENT_SHT_SIM_STOP
std::cout << «nEvent EVENT_SHT_SIM_STOP» << evt->dwData;
break;
default:
break;
} // Завершение switch RECV_EVENT
break;
}
case SIMCONNECT_RECV_ID_QUIT:
{
quit = 1;
break;
}
default:
break;
} // завершение switch pData->dwID
}
// === Пользовательская функция включения извещений о событиях в FSX ===============
void ShtEvent()
{
ShtHr = SimConnect_SubscribeToSystemEvent(hSimConnect, EVENT_SHT_SIM, «Sim»);
ShtHr = SimConnect_SubscribeToSystemEvent(hSimConnect, EVENT_SHT_SIM_START, «SimStart»);
ShtHr = SimConnect_SubscribeToSystemEvent(hSimConnect, EVENT_SHT_SIM_STOP, «SimStop»);
while (0 == quit)
{
SimConnect_CallDispatch(hSimConnect, ShtDispatchProcReadTXT, NULL); // Включаем в функцию обратной связи нашу функцию (ShtDispatchProcReadTXT) о событиях в FSX
Sleep (1);
}
}
// ========= Главная функция программы С++ ===========
int __cdecl _tmain(int argc, _TCHAR* argv[])
{
ShtSimCntOpen();
ShtEvent();
ShtSimCntClose();
return 0;
}
Сообщение отредактировал dmi-shef: 10 December 2012 — 18:14
Что-то вообще — не из оперы.
Лучше перефразировать или если непонятен механизм — убрать вообще.
Еще.
Свое приложение, все же лучше делать не отдельным exe-фалом, который нужно прописывать в EXE.xml и который сим будет запускать вначале своего старта, а все же приборной dll, которая загружается симом только при старте полета с данной моделью. Как это сделать — говорили и есть пример.
Если же замутили нечто, не относящееся к конкретной модели самолета, то тогда лучше сделать тоже dll, но прописать ее уже в DLL.xml, что бы dll загружалась симом при его старте, но при этом не висело, совершенно никому ненужное консольное окно. Т.е. что бы dll себя проявляла только полезным результатом.
В dll не надо крутить цикл с вызовом SimConnect_CallDispatch. Достаточно один раз, в инициализации dll (в DLLStart) вызвать один раз SimConnect_CallDispatch и далее уже DispatchProc будет вызываться автоматически, если произошло любое из системных сабытий, на которые Вы подписались или событие, к которому в примапились с помощью функций типа SimConnect_MapClientEventToSimEvent, SimConnect_MapInputEventToClientEvent, в том числе и события изменения данных.
Вот цитата из доки SDK:
// Include files are no different than for an EXE HANDLE hSimConnect = NULL; void CALLBACK MyDispatchProcDLL(SIMCONNECT_RECV* pData, DWORD cbData, void *pContext) { // Callback code for a DLL is no different than for an EXE } // // The DLLStart function must be present. // int __stdcall DLLStart(void) { HRESULT hr; if (SUCCEEDED(SimConnect_Open(&hSimConnect, "DLL name", NULL, 0, NULL, 0))) { printf("nConnected to Flight Simulator"); // Place all initialization code for the client in this function [b]hr = SimConnect_CallDispatch(hSimConnect, MyDispatchProcDLL, NULL);[/b] } return 0; } // // The DLLStop function must be present. // void __stdcall DLLStop(void) { // Close the client if (hSimConnect != NULL) HRESULT hr = SimConnect_Close(hSimConnect); }Отдельный exe необходим только на компе, где нет FSX, а есть только Ваша прога, которая взаимодействует с FSX по сети и выполняет, какую-то полезную работу.
Сообщение отредактировал serg_p: 28 November 2012 — 21:01
Я имел ввиду, что эти функции можно помещать как в пользовательскую функцию (в моем случае void ShtEvent(), или непосредственно в главную функцию программы. В отличие от CALLBACK DispatchProc, которая в главную программу устанавливаться не хочет.
Но эта фраза не является ключевой, поэтому убрал.
DispatchProc никто не должен вызывать кроме SimConnect-а. Т.е. ни Ваш код, ни еще чей-либо. Это CallBack-функция, функция обратного вызова. Ее вызывает только тот механизм, которому Вы передали указатель на эту функцию в инициализации. В данном случае ее вызывает только SimConnect и, в зависимости от случая, иногда засылает в нее указатели на разные структуры данных, соответствующие данному контексту. Собственно так действуют все CallBack-и.
CallBack-функции являются одной из важнейших частей механизма взаимодействия клиента и сервера. Клиент посылает запрос, вызвав некоторую функцию API, а сервер в ответ, когда посчитает нужным, через свой интерфейсный механизм вызывает CallBack-функцию, возвращая клиенту запрошенные данные. Все это сопровождается передачей некоторого ID, по которому клиент определяет — в ответ на что произошел этот вызов. Бывает, что просто CallBack вызывается при наступлении некого события без кокой либо пересылки данных. Просто засылкой некого ID в CallBack, сервер говорит клиенту, что произошло вот такое-то событие.
В случае с SimConnect-ом, клиент — это Ваша программа, сервер — это FSX, а SimConnect — интерфейсный механизм. Собсвенно из названия следует — коннект к симу.
Сообщение отредактировал serg_p: 28 November 2012 — 22:32
========================
Продолжение записок по API функциям SimConnect SDK, начало см. пост #29 этой темы http://www.avsim.su/…0#entry2279836.
Кроме системных событий в FSX есть большая группа событий, связанных с самолетом — состояние самолета, работа его систем, приборов и т.д. Собственно, это основная группа событий для создателей приборов.
Получение извещений об этих событиях является важнейшей частью организации работы как систем самолета и его поведения в FSX, так и логики их работы.
Есть еще одна группа событий FSX — так называемые глобальные события. К сожалению, в SDK FSX их определение дано нечетко, поэтому я отнес к ним события, связанные с работой ATC.
Обе эти группы событий имеют одинаковую организацию получения извещений, поэтому будем рассматривать их вместе.
Перечень событий, связанных с самолетом, и глобальных событий, приведены в описании SDK FSX в разделе VariablesEvent IDs. На скрине показан фрагмент таблицы переменных событий. Для SimConnect используются строковые имена, указанные во втором столбце этой таблицы.
Прикрепленные изображения
========================
Продолжение записок по API функциям SimConnect SDK, начало см. пост #29 этой темы http://www.avsim.su/…0#entry2279836.
Описание API функций глобальных событий и событий, связанных с самолетом.
Конвертируем программу, подключаем ее к FSX, запускаемся.
Выпускаем закрылки на полный угол (нажимаем F8). В консольном окне получаем сообщение о событии.
Теперь можно полученное сообщение использовать в своих функциях для решения поставленной задачи.
Прикрепленные изображения
========================
Продолжение записок по API функциям SimConnect SDK, начало см. пост #29 этой темы http://www.avsim.su/…0#entry2279836.
Для получения извещений о событиях, связанных с самолетом и глобальных событиях в SimConnect есть три замечательные API функции:
ShtHr = SimConnect_MapClientEventToSimEvent(hSimConnect, EVENT_SHT_FLAPS_DOWN, «FLAPS_DOWN»);
ShtHr = SimConnect_AddClientEventToNotificationGroup(hSimConnect, GROUP_ShtPlane, EVENT_SHT_FLAPS_DOWN);
ShtHr = SimConnect_SetNotificationGroupPriority(hSimConnect, GROUP_ShtPlane, SIMCONNECT_GROUP_PRIORITY_HIGHEST);
Первая функция связывает событие FSX с пользовательской переменной этого события. В SDK применен термин «подписка на событие». Вот с помощью этой функции …Map пользователь подписывается на получение извещений о событии и получает его через функцию SimConnect_CallDispatch, о которой уже говорилось выше.
Параметрами первой функции SimConnect_MapClientEventToSimEvent() являются, кроме известного нам hSimConnect, еще два:
EVENT_SHT_FLAPS_DOWN — пользовательская переменная события. Ее имя определяет пользователь по своему усмотрению для обозначения события;
«FLAPS_DOWN» — строковое имя события Event ID из таблицы Event IDs SDK.
Таким образом, пользователь получает жесткую связь значения своей переменной (т.е. события клиента) с событием в FSX (т.е. события сервера).
Вторая и третья функции позволяют упорядочить получаемые извещения о событиях клиента и группируют их по функциональному признаку.
Вторая функция включает пользовательское событие в группу.
Третья функция устанавливает приоритет этой группы.
В принципе при малом количестве событий можно обойтись только одной первой функцией, но лучше применять группировку для рациональной организации работы.
Параметрами второй функции SimConnect_AddClientEventToNotificationGroup(), кроме hSimConnect, являются два других параметра:
GROUP_ShtPlane — имя группы, в которую включается событие клиента. Имя группе дает пользователь по своему усмотрению.
EVENT_SHT_FLAPS_DOWN — пользовательская переменная события, которое описано в первой функции.
Параметрами третьей функции SimConnect_SetNotificationGroupPriority(), кроме hSimConnect, являются два других параметра:
GROUP_ShtPlane — имя нашей группы;
SIMCONNECT_GROUP_PRIORITY_HIGHEST — приоритет нашей группы, в данном случае наивысший (HIGHEST). Возможные приоритеты описаны в SDK, их понимание не представляет трудностей.
Таким образом, применяя связку из описанных трех функций и функции CallDispatch, можно легко получить извещение о любом глобальном событии и событии, связанном с самолетом.
Сообщение отредактировал dmi-shef: 10 December 2012 — 15:07
========================
Продолжение записок по API функциям SimConnect SDK, начало см. пост #29 этой темы http://www.avsim.su/…0#entry2279836.
Описание API функций глобальных событий и событий, связанных с самолетом.
Приведу пример получения событий, связанных с самолетом и глобальных событиях. Он сделан на основе примеров SDK исключительно для иллюстрации возможностей API функций, а не для показа правильной организации программы.
#include <windows.h>
……
#include «SimConnect.h»
// =============== Определяем глобальные переменные ===================
HRESULT ShtHr;
HANDLE hSimConnect = NULL; // Handle to a SimConnect object
// ============= Определяем события и группы событий ====================
enum GROUP_ID // Объявляем группу событий
{
GROUP_ShtPlane, // Группа событий, связанных с системами самолета
GROUP_ShtG1000, // Группа событий, связанных с Garmin1000
};
enum EVENT_ID // Определяем пользовательские события. Имя события состоит из слова EVENT_ и имени ID события из перечня Event IDs SDK
{
EVENT_SHT_FLAPS_UP, // ID событие — выпущены закрылки;
EVENT_SHT_FLAPS_DOWN, // ID событие — убраны закрылки;
EVENT_SHT_G1000_MFD_FLIGHTPLAN_BUTTON, // ID событие — нажата кнопка FLP на дисплее MFD Garmin1000.
};
// =========== Функция обратной связи, сообщает о событиях в FSX ===========================
void CALLBACK ShtDispatchProcReadTXT(SIMCONNECT_RECV *pData, DWORD cbData, void *pContext)
{
switch(pData->dwID) // Доступ к атрибуту через указатель pData на объект dwID, т.е. объект с ID, указанным ниже
{
case SIMCONNECT_RECV_ID_EVENT:
{
SIMCONNECT_RECV_EVENT *evt = (SIMCONNECT_RECV_EVENT*)pData;
switch(evt->uEventID) // Доступ к атрибуту evt через указатель на объект uEventID
{
case EVENT_SHT_FLAPS_UP: // Здесь указатель на ID -> EVENT_SHT_FLAPS_UP
std::cout << «nEvent EVENT_FLAPS_UP» << evt->dwData << «n»;
break;
case EVENT_SHT_FLAPS_DOWN: // Здесь указатель на ID -> EVENT_SHT_FLAPS_DOWN
std::cout << «nEvent EVENT_FLAPS_DOWN» << evt->dwData << «n»;
break;
case EVENT_SHT_G1000_MFD_FLIGHTPLAN_BUTTON: // Здесь указатель на ID -> EVENT_SHT_G1000_MFD_FLIGHTPLAN_BUTTON
std::cout << «nEvent EVENT_G1000_MFD_FLIGHTPLAN_BUTTON» << evt->dwData << «n»;
break;
default:
break;
} // Завершение switch RECV_EVENT
break;
}
case SIMCONNECT_RECV_ID_QUIT:
{
quit = 1;
break;
}
default:
break;
} // завершение switch pData->dwID
}
// ========= Пользовательская функция получения извещений о событиях ============
void ShtEvent()
{
HRESULT ShtHr;
ShtHr = SimConnect_MapClientEventToSimEvent(hSimConnect, EVENT_SHT_BRAKES, «BRAKES»); // Ассоциируем ID клиента с ID FSX. В данном случае ID клиента — EVENT_KEY_BRAKES, ID FSX — BRAKES
ShtHr = SimConnect_AddClientEventToNotificationGroup(hSimConnect, GROUP_ShtPlane, EVENT_SHT_BRAKES); // Добавляем событие ID клиента (EVENT_KEY_BRAKES) в группу уведомления GROUP_Sht0
ShtHr = SimConnect_SetNotificationGroupPriority(hSimConnect, GROUP_ShtPlane, SIMCONNECT_GROUP_PRIORITY_HIGHEST); // Устанавливаем наивысший приоритет группы уведомлений
ShtHr = SimConnect_MapClientEventToSimEvent(hSimConnect, EVENT_SHT_FLAPS_DOWN, «FLAPS_DOWN»);
ShtHr = SimConnect_AddClientEventToNotificationGroup(hSimConnect, GROUP_ShtPlane, EVENT_SHT_FLAPS_DOWN);
ShtHr = SimConnect_SetNotificationGroupPriority(hSimConnect, GROUP_ShtPlane, SIMCONNECT_GROUP_PRIORITY_HIGHEST);
ShtHr = SimConnect_MapClientEventToSimEvent(hSimConnect, EVENT_SHT_G1000_MFD_FLIGHTPLAN_BUTTON, «G1000_MFD_FLIGHTPLAN_BUTTON»);
ShtHr = SimConnect_AddClientEventToNotificationGroup(hSimConnect, GROUP_ShtPlane, EVENT_SHT_G1000_MFD_FLIGHTPLAN_BUTTON);
ShtHr = SimConnect_SetNotificationGroupPriority(hSimConnect, GROUP_ShtPlane, SIMCONNECT_GROUP_PRIORITY_HIGHEST);
while (0 == quit)
{
SimConnect_CallDispatch(hSimConnect, ShtDispatchProcReadTXT, NULL); // Включаем в функцию обратной связи нашу функцию (ShtDispatchProcReadTXT) о событиях в FSX
Sleep (1);
}
}
// Главная программа С++
//———————————
int __cdecl _tmain(int argc, _TCHAR* argv[])
{
ShtSimCntOpen();
ShtEvent();
ShtSimCntClose();
return 0;
}
Сообщение отредактировал dmi-shef: 12 January 2013 — 13:43
Думаю тут стоит упомянуть про четвертый параметр bool bMaskable во второй функции. Иногда надо замаскировать евент, чтоб дальше клиента не уходило. Например для раздельного отключения осей джойстика.
enum GROUP_ID { GROUP_AXIS, }; enum EVENT_ID { EVENT_XAXIS, EVENT_YAXIS, }; hr=SimConnect_MapClientEventToSimEvent(hSimConnect,EVENT_XAXIS,"AXIS_AILERONS_SET"); hr=SimConnect_MapClientEventToSimEvent(hSimConnect,EVENT_YAXIS,"AXIS_ELEVATOR_SET"); hr=SimConnect_AddClientEventToNotificationGroup(hSimConnect,GROUP_AXIS,EVENT_XAXIS,false); hr=SimConnect_AddClientEventToNotificationGroup(hSimConnect,GROUP_AXIS,EVENT_YAXIS,true); hr=SimConnect_SetNotificationGroupPriority(hSimConnect_GROUP_AXIS,SIMCONNECT_GROUP_PRIORITY_HIGHEST_MASKABLE);Тут канал тангажа не будет реагировать на ось Y джойстика, крен будет работать как обычно от джойстика.
Чтоб поменять замаскированное значение, надо не забыть убрать евент из нотфикации. Пример возвращения оси Y
Сообщение отредактировал fsfreelancer: 12 December 2012 — 08:22