upnp 使用cling编写service

package example.binarylight;

import org.teleal.cling.binding.annotations.UpnpAction;
import org.teleal.cling.binding.annotations.UpnpInputArgument;
import org.teleal.cling.binding.annotations.UpnpOutputArgument;
import org.teleal.cling.binding.annotations.UpnpService;
import org.teleal.cling.binding.annotations.UpnpServiceId;
import org.teleal.cling.binding.annotations.UpnpServiceType;
import org.teleal.cling.binding.annotations.UpnpStateVariable;

@UpnpService(
        serviceId = @UpnpServiceId("ElectricfanService"),  //serviceId
        serviceType = @UpnpServiceType(value = "ElectricfanService", version = 1) //SERVICE TYPE 和版本
)
public class ElectricfanService {

    @UpnpStateVariable(defaultValue = "0", sendEvents = false)
    private boolean target = false;

    @UpnpStateVariable(defaultValue = "0")
    private boolean status = false;

    @UpnpAction
    public void setTarget(@UpnpInputArgument(name = "NewTargetValue")
                          boolean newTargetValue) {
        target = newTargetValue;
        status = newTargetValue;
        System.out.println("myService is: " + status);
    }

    @UpnpAction(out = @UpnpOutputArgument(name = "RetTargetValue"))
    public boolean getTarget() {
        return target;
    }

    @UpnpAction(out = @UpnpOutputArgument(name = "ResultStatus"))
    public boolean getStatus() {
        return status;
    }
    
    @UpnpStateVariable(defaultValue = "0", sendEvents = false)
    private String aa;

    @UpnpAction
    public void setAa(@UpnpInputArgument(name = "rr")
    		String rr) {
        aa = rr;
        System.out.println("myService setAa is: " + rr);
    }
 }

1、 target和status是官方文档里面例子,暂时不明白为什么需要两个参数。

2、@UpnpStateVariable(defaultValue = "0", sendEvents = false)
    private String aa;

可以直接改为:

@UpnpStateVariable
    private String aa;

不知道这样有什么影响。

3、aa是自己写的变量,使用string类型,提供一个action方法,要求符合java bean规范:setAa这种写法。rr是控制点传入参数Key值,输入输出使用key value的形式。

4、控制点调用如下:

基本使用官方demo

package example.binarylight;

import java.net.URI;
import java.net.URISyntaxException;

import org.teleal.cling.UpnpService;
import org.teleal.cling.UpnpServiceImpl;
import org.teleal.cling.controlpoint.ActionCallback;
import org.teleal.cling.model.action.ActionInvocation;
import org.teleal.cling.model.message.UpnpResponse;
import org.teleal.cling.model.message.header.STAllHeader;
import org.teleal.cling.model.meta.RemoteDevice;
import org.teleal.cling.model.meta.Service;
import org.teleal.cling.model.types.InvalidValueException;
import org.teleal.cling.model.types.ServiceId;
import org.teleal.cling.model.types.UDAServiceId;
import org.teleal.cling.registry.DefaultRegistryListener;
import org.teleal.cling.registry.Registry;
import org.teleal.cling.registry.RegistryListener;

public class ElectricfanClient implements Runnable {

    public static void main(String[] args) throws Exception {
        // Start a user thread that runs the UPnP stack
        Thread clientThread = new Thread(new ElectricfanClient());
        clientThread.setDaemon(false);
        clientThread.start();

    }

    public void run() {
        try {

            UpnpService upnpService = new UpnpServiceImpl();

            // Add a listener for device registration events
            upnpService.getRegistry().addListener(
                    createRegistryListener(upnpService)
            );

            // Broadcast a search message for all devices
            upnpService.getControlPoint().search(
                    new STAllHeader()
            );

        } catch (Exception ex) {
            System.err.println("Exception occured: " + ex);
            System.exit(1);
        }
    }

    // DOC: REGISTRYLISTENER
    RegistryListener createRegistryListener(final UpnpService upnpService) {
        return new DefaultRegistryListener() {

            ServiceId serviceId = new UDAServiceId("ElectricfanService");

            @Override
            public void remoteDeviceAdded(Registry registry, RemoteDevice device) {

                Service switchPower;
                if ((switchPower = device.findService(serviceId)) != null) {

                    System.out.println("Service discovered: " + switchPower);
                    executeAction(upnpService, switchPower);

                }

            }

            @Override
            public void remoteDeviceRemoved(Registry registry, RemoteDevice device) {
                Service switchPower;
                if ((switchPower = device.findService(serviceId)) != null) {
                    System.out.println("Service disappeared: " + switchPower);
                }
            }

        };
    }
    // DOC: REGISTRYLISTENER
    // DOC: EXECUTEACTION
    void executeAction(UpnpService upnpService, Service switchPowerService) {

            ActionInvocation setTargetInvocation =
                    new SetTargetActionInvocation(switchPowerService);

            // Executes asynchronous in the background
            upnpService.getControlPoint().execute(
                    new ActionCallback(setTargetInvocation) {

                        @Override
                        public void success(ActionInvocation invocation) {
                            assert invocation.getOutput().length == 0;
                            System.out.println("Successfully called action!");
                        }

                        @Override
                        public void failure(ActionInvocation invocation,
                                            UpnpResponse operation,
                                            String defaultMsg) {
                            System.err.println(defaultMsg);
                        }
                    }
            );

    }
//    class SetTargetActionInvocation extends ActionInvocation {
//
//        SetTargetActionInvocation(Service service) {
//            super(service.getAction("SetTarget"));
//            try {
//
//                // Throws InvalidValueException if the value is of wrong type
//                setInput("NewTargetValue", true);
//
//            } catch (InvalidValueException ex) {
//                System.err.println(ex.getMessage());
//                System.exit(1);
//            }
//        }
//    }
    class SetTargetActionInvocation extends ActionInvocation {
        SetTargetActionInvocation(Service service) {
            super(service.getAction("SetAa"));
            try {
                // Throws InvalidValueException if the value is of wrong type
                setInput("rr", "1234");
            } catch (InvalidValueException ex) {
                System.err.println(ex.getMessage());
                System.exit(1);
            }
        }
    }
    
    // DOC: EXECUTEACTION
}

主要区别在于:

1、 ServiceId serviceId = new UDAServiceId("ElectricfanService");

定义为自己需要的service

2、 super(service.getAction("SetAa"));
调用自己定义的action

3、传入自己的key value

  setInput("rr", "1234");

以上基本实现控制点控制设备的服务功能。

按照理解,UPnP-av-ContentDirectory-v1-Service应该也是通过这种方式的,无非自己定义通讯的key value,加上设备需要启动一个web容器,然后提供对外资源暴露的功能。

以控制电风扇例子为例,简单家电需要提供的服务如下:

1、开关功能。 (电风扇开关)

2、功能列表查询功能。 (档位控制,定时控制)

3、具体功能控制

   a、档位增减

   b、定时多少

一般设备功能:

1、开关

2、控制量的增减

3、定时

难点:

1、设备要求支持网络模块(upnp协议)以及服务的实现

2、控制点可以为电脑,智能手机。

猜你喜欢

转载自smallbee.iteye.com/blog/1602234