Switch to unified view

a b/hello_src/hellodevice.cpp
1
// A barebones example of device implementation.
2
//
3
// The skeleton code for the Service part could have been
4
// automatically generated by the scripts/sdeftoc.py (libupnpp source
5
// tree), from the xml description, but we did it by hand instead.
6
//
7
// This is a minimal example. Refer to, e.g. the upmpdcli code for a
8
// more complete exercise of the library.
9
#include <iostream>
10
11
#include <libupnpp/device/device.hxx>
12
#include <libupnpp/soaphelp.hxx>
13
#include <libupnpp/log.hxx>
14
15
using namespace std;
16
using namespace std::placeholders;
17
using namespace UPnPProvider;
18
using namespace UPnPP;
19
20
// Beware: these must match the values for serviceType and serviceId in the
21
// device description document
22
const string sTpHello("urn:upnpp-schemas:service:HelloService:1");
23
const string sIdHello("urn:upnpp-org:serviceId:HelloService");
24
25
// Device description document. This has some identifying data and a
26
// list of services.
27
// Beware: the UDN value must match the uuid parameter for the device
28
// constructor, and the SCDPURL paths must match the vdircontent paths
29
// (see below)
30
const string devicedesc(R"raw(<?xml version="1.0"?>
31
<root xmlns="urn:schemas-upnp-org:device-1-0">
32
  <specVersion><major>1</major><minor>0</minor></specVersion>
33
  <device>
34
    <deviceType>urn:upnpp-schemas:device:HelloDevice:1</deviceType>
35
    <friendlyName>HelloDeviceName</friendlyName>
36
    <manufacturer>HelloDevices</manufacturer>   
37
    <modelName>SimpleHelloDevice</modelName>
38
    <modelNumber>1.0</modelNumber>
39
    <UDN>uuid:you-should-find-something-better</UDN>
40
    <serviceList>
41
      <service>
42
        <serviceType>urn:upnpp-schemas:service:HelloService:1</serviceType>
43
        <serviceId>urn:upnpp-org:serviceId:HelloService</serviceId>
44
        <SCPDURL>/hello/Hello.xml</SCPDURL>
45
        <controlURL>/ctl/Hello</controlURL>
46
        <eventSubURL>/evt/Hello</eventSubURL>
47
      </service>
48
    </serviceList>
49
  </device>
50
  <devicelist>
51
  </devicelist>
52
</root>
53
)raw");
54
55
// Service description document. The variables and actions. Action
56
// names must match the name parameter to the addActionMapping calls
57
const string helloservicedesc(R"raw(<?xml version="1.0" encoding="utf-8"?>
58
<scpd xmlns="urn:schemas-upnp-org:service-1-0">
59
  <specVersion><major>1</major><minor>1</minor></specVersion>
60
  <actionList>
61
    <action>
62
      <name>Hello</name>
63
      <argumentList>
64
        <argument>
65
          <name>MyValue</name>
66
          <direction>out</direction>
67
          <relatedStateVariable>Hello</relatedStateVariable>
68
        </argument>
69
      </argumentList>
70
    </action>
71
  </actionList>
72
  <serviceStateTable>
73
    <stateVariable sendEvents="no">
74
      <name>Hello</name>
75
      <dataType>string</dataType>
76
    </stateVariable>
77
  </serviceStateTable>
78
</scpd>
79
)raw");
80
81
// The files which will be served by the HTTP server. Refer to the
82
// comments in device.hxx for more details.
83
unordered_map<string, VDirContent> myfiles {
84
    {"/hello/description.xml", {devicedesc, "text/xml"}},
85
    {"/hello/Hello.xml", {helloservicedesc, "text/xml"}},
86
        };
87
88
// The service class defines the methods which will be called for each
89
// UPnP action (and the event handling, which is not shown here).
90
class HelloService : public UPnPProvider::UpnpService {
91
public:
92
93
    // The constructor initializes the base class (which links to the
94
    // device and lib), and sets our action callbacks.
95
    HelloService(UpnpDevice *dev)
96
        : UpnpService(sTpHello, sIdHello, dev), m_dev(dev) {
97
98
        m_dev->addActionMapping(this, "Hello", 
99
                            bind(&HelloService::hello, this, _1, _2));
100
101
    }
102
103
    // Event retrieval routine. This gets polled (the service can
104
    // trigger an immediate poll). We're not really doing this, look
105
    // at how upmpdcli openhome services do it
106
    virtual bool getEventData(bool all, std::vector<std::string>& names, 
107
                              std::vector<std::string>& values) {
108
        return true;
109
    }
110
111
private:
112
113
    // An action method. This takes no argument, just returns a value.
114
    // Look at upmpdcli code to see how to handle incoming parameters.
115
    int hello(const SoapIncoming& sc, SoapOutgoing& data) {
116
        
117
        data.addarg("MyValue", "World");
118
        return UPNP_E_SUCCESS;
119
    }
120
121
    UpnpDevice *m_dev;
122
};
123
124
// The device initializes the parent class and creates its services
125
class HelloDevice : public UpnpDevice {
126
public:
127
    HelloDevice(const string& deviceid,
128
                const std::unordered_map<std::string, VDirContent>& files)
129
        : UpnpDevice(deviceid, files) {
130
        m_services.push_back(new HelloService(this));
131
    }
132
133
    ~HelloDevice() {
134
        for (auto& ent : m_services) {
135
            delete ent;
136
        }
137
    }
138
    vector<UpnpService*> m_services;
139
};
140
141
142
int main(int argc, char *argv[])
143
{
144
    // Initialize libupnpp logging
145
    Logger::getTheLog("")->setLogLevel(Logger::LLERR);
146
147
    //cout << "DEVICE: " << devicedesc << endl;
148
    //cout << "SERVICE: " << helloservicedesc << endl;
149
150
    // uuid must match the one in the description document
151
    HelloDevice dev("uuid:you-should-find-something-better", myfiles);
152
153
    string host;
154
    unsigned short port;
155
    dev.ipv4(&host, &port);
156
157
    // fname should match what we set in the desc above ! A real
158
    // program would do it differently...
159
    string fname("HelloDeviceName");
160
161
    cout << fname << " running on host " << host << " port " << port << endl;
162
163
    dev.eventloop();
164
}