1
2
3
4
5 """ Device-side service implementation. Used for implementing and deploying
6 UPnP services.
7 """
8
9 from os import path, mkdir
10
11 from brisa.core import log, config, failure, webserver
12
13 from brisa.upnp.base_service import BaseService, BaseStateVariable
14 from brisa.upnp.base_service_builder import BaseServiceBuilder
15 from brisa.upnp.device.action import Action, Argument
16 from brisa.upnp.device.event import EventController
17 from brisa.upnp.device.xml_gen import ServiceXMLBuilder
18 from brisa.upnp import soap
19
20
22 """ Wrapper for an error code. Contains a status attribute that corresponds
23 with the error code.
24 """
25
28
29
32
33
35
36 - def __init__(self, service, name, send_events, multicast, data_type, values=[]):
39
40
42
48
50 return Argument(arg_name, arg_direction, arg_state_var)
51
57
62
63
65 """ Wrapper for receiving soap calls and assigning them to correspondent
66 methods. Extend UPnPPublisher and add the class to the web server as a
67 resource and your methods will be exported.
68 """
69 encoding = "UTF-8"
70
71 - def __init__(self, service, service_type):
75
76 - def render(self, uri, request, response):
77 """ Renders a request received.
78 """
79 data = request.read()
80 headers = request.headers
81
82 method_name, args, kwargs, ns = soap.parse_soap_call(data)
83 try:
84 headers['content-type'].index('text/xml')
85 except:
86
87 return self._build_error(failure.Failure(ErrorCode(415)), request,
88 method_name, response)
89
90 function = self.lookup_function(method_name)
91
92 if not function:
93 return self._method_not_found(request, response, method_name)
94 else:
95 return self._get_call_response(request, response, method_name,
96 function, *args, **kwargs)
97
98 return ['']
99
101 """ Lookup published SOAP function.
102 """
103 log.info('Finding service action %s' % function_name)
104 for action_name, action in self.service._actions.iteritems():
105 if action_name == function_name:
106 return action
107 log.info('Action %s not founded' % function_name)
108 return None
109
110 - def _get_call_response(self, request, response_obj, method_name,
111 function, *args, **kwargs):
112 """ Performs the soap call, builds and returns a response.
113 """
114 result = function(*args, **kwargs)
115
116 ns = self.service_type
117 try:
118 method = result.keys()[0]
119 result = result[method]
120 except AttributeError, IndexError:
121 result = {}
122 method = ''
123 response = soap.build_soap_call("{%s}%s" % (ns, method),
124 result, encoding=None)
125 return self._build_response(request, response, response_obj)
126
127 - def _build_error(self, failure, request, method_name, response_obj):
141
142 - def _build_response(self, request, response, response_object, status=200):
143 """ Builds a response for a call.
144 """
145 if status == 200:
146 response_object.status = 200
147 else:
148 response_object.status = 500
149
150 if self.encoding is not None:
151 mime_type = 'text/xml; charset="%s"' % self.encoding
152 else:
153 mime_type = "text/xml"
154 response_object.headers["Content-type"] = mime_type
155 response_object.headers["Content-length"] = str(len(response))
156 response_object.headers["EXT"] = ''
157 response_object.body = response
158 return response
159
166
167
169
170 - def __init__(self, id, serv_type, url_base='',
171 scpd_xml_filepath='', presentation_controller=None):
172 BaseService.__init__(self, id, serv_type, url_base)
173
174 self.control_controller = ServiceController(self, self.service_type)
175 self.eventSub_controller = None
176 self.presentation_controller = presentation_controller
177
178 if not scpd_xml_filepath:
179 self._generate_xml()
180 self._create_xml = True
181 else:
182 self._xml_filepath = scpd_xml_filepath
183 fd = open(self._xml_filepath, 'r')
184 if not ServiceBuilder(self, fd).build():
185 raise InvalidService('Error building the service %s' % id)
186 fd.close()
187 self._create_xml = False
188
208
210 if not self.eventSub_controller and state_variable.send_events:
211 self.eventSub_controller = EventController(self)
212 self._state_variables[state_variable.name] = state_variable
213
215 state_variable = self._state_variables[name]
216 state_variable.update(value)
217
221
222 - def start(self, *args, **kwargs):
224
226 self.xml_filename = '%s-scpd.xml' % self.id
227 self.xml_filename = self.xml_filename.replace(' ', '')
228 self._xml_filepath = path.join(config.manager.brisa_home, 'tmp_xml')
229 if not path.exists(self._xml_filepath):
230 mkdir(self._xml_filepath)
231 self._xml_filepath = path.join(self._xml_filepath, self.xml_filename)
232