Реализация устройства BinaryLight

Пример устройства/сервиса UPnP, реализующего устройство BinaryLight и сервис SwitchPower для эмуляции выключателя света.

Пользовательский интерфейс сделан максимально простым для демонстрации базовых концепций и методов.

Пример #1 Реализация сервера управления освещением

<?php

/* SetTarget */
function set_target_cb($service$action$arg)
{
    
/* Получаем новое целевое значение */
    
$target gupnp_service_action_get($action'NewTargetValue'GUPNP_TYPE_BOOLEAN);

    
/* Если новая цель не соответствует текущему состоянию, изменить состояние и послать 
        уведомление о том, что статус изменился. */
    
if ($target != $GLOBALS['status']) {
        
$GLOBALS['status'] = $target;
        
gupnp_service_notify($service'Status'GUPNP_TYPE_BOOLEAN$GLOBALS['status']);
        
printf("Свет сейчас %s.\n"$GLOBALS['status'] ? "включен" "выключен");
    }

    
/* Вернуть коиенту статус успеха */
    
gupnp_service_action_return($action);
}

/* GetTarget */
function get_target_cb($service$action$arg)
{
    
gupnp_service_action_set($action'RetTargetValue'GUPNP_TYPE_BOOLEAN$GLOBALS['status']);
    
gupnp_service_action_return($action);
}

/* GetStatus */
function get_status_cb($service$action$arg)
{
    
gupnp_service_action_set($action'ResultStatus'GUPNP_TYPE_BOOLEAN$GLOBALS['status']);
    
gupnp_service_action_return($action);
}

/* По умолчанию свет выключен */
$GLOBALS['status'] = false;
printf("Свет сейчас %s.\n"$GLOBALS['status'] ? "включен" "выключен");

/* Создаем контекст UPnP */
$context gupnp_context_new();
if (!
$context) {
    
printf("Ошибка создания контекста GUPnP\n");
    exit(-
1);
}

/* Директория, содержащая файлы описания устройства и сервиса */
gupnp_context_host_path($context"./web""");

/* Создаем корневое устройство */
$location "/BinaryLight.xml";
$dev gupnp_root_device_new($context$location);
gupnp_root_device_set_available($devtrue);

/* Получение сервиса переключения из корневого устройства */
$service_type "urn:schemas-upnp-org:service:SwitchPower:1";
$service gupnp_device_info_get_service($dev$service_type);
if (!
$service) {
    die(
"Не удается получить сервис SwitchPower1\n");
}

/* Устанавливаем callback для GetStatus */
gupnp_device_action_callback_set($serviceGUPNP_SIGNAL_ACTION_INVOKED"GetStatus"
    
"get_status_cb""action data, GetStatus");

/* Устанавливаем callback для GetTarget */
gupnp_device_action_callback_set($serviceGUPNP_SIGNAL_ACTION_INVOKED"GetTarget"
    
"get_target_cb""action data, GetTarget");

/* Устанавливаем callback для SetTarget */
gupnp_device_action_callback_set($serviceGUPNP_SIGNAL_ACTION_INVOKED"SetTarget"
    
"set_target_cb""action data, SetTarget");

/* Запускаем главный цикл */
gupnp_root_device_start($dev);

?>

Пример #2 Реализация клиента управления освещением

<?php

function service_proxy_available_cb($proxy$arg)
{
    
$mode $arg['mode'];

    
printf("Установить подписку\n");
    
gupnp_service_proxy_set_subscribed($proxytrue);

    
/* Добавляем оповещение при изменении статуса */
    
if (!gupnp_service_proxy_add_notify($proxy"Status"
            
GUPNP_TYPE_BOOLEAN"status_changed_cb"NULL)) {
        
printf("Не удалось добавить уведомление\n");
    }
    
    if (
$mode == 'TOGGLE') {
        
/* При переключении для начала выясняем текущий статус */
        
$target gupnp_service_proxy_action_get($proxy'GetStatus''ResultStatus'GUPNP_TYPE_BOOLEAN);

        
/* А потом меняем его */
        
$target = ! $target;
    } else {
        
/* Режим - это логическое значение */
        
$target = ($mode == 'ON') ? true false;
    }

    
/* Устанавливаем цель */
    
if (!gupnp_service_proxy_action_set($proxy'SetTarget''NewTargetValue'$targetGUPNP_TYPE_BOOLEAN)) {
        
printf("Невозможно установить переключатель\n");
    } else {
        
printf("Установите переключатель в %s.\n"$target "включен" "выключен");
    }
    
    
/* Останавливаем просмотр */
    
gupnp_control_point_browse_stop($arg['cp']);
}

function 
status_changed_cb($variable$value$arg)
{
    
printf("Статус был изменен\n");
    
printf("\tимя переменной: %s\n"$variable);
    
printf("\tзначение: %s\n", (int)$value);
    
printf("\n");
}

/* Разбираем аргументы командной строки */
if (count($argv) != 2) {
    
printf("Использование: light-client.php [on|off|toggle]\n");
    exit(-
1);
}

if (
$argv[1] == "on") {
    
$mode 'ON';
} elseif (
$argv[1] == "off") {
    
$mode 'OFF';
} elseif (
$argv[1] == "toggle") {
    
$mode 'TOGGLE';
} else {
    
usage ();
    exit(-
1);
}

/* Создаем контекст UPnP */
$context gupnp_context_new();
if (!
$context) {
    
printf("Ошибка создания контекста GUPnP\n");
    exit(-
1);
}

/* Создаем контрольную точку, ищем сервис SwitchPower */
$cp gupnp_control_point_new ($context,
        
"urn:schemas-upnp-org:service:SwitchPower:1");

/* Соединяемся с callback-функцией поиска сервиса */
$cb "service_proxy_available_cb";
$arg = array('mode' => $mode'cp' => $cp);
gupnp_control_point_callback_set($cpGUPNP_SIGNAL_SERVICE_PROXY_AVAILABLE$cb$arg);

/* Начинаем просмотр */
gupnp_control_point_browse_start($cp);

?>