""" A simple example that will place a call and send a fax. Actions: - place a call - send a fax - hang up This sample uses two documents, a 'header' page and the fax 'body'. It is assumed that application_parameters is the name of the header page, and outbound_parameters is the name of the body. Several other assumptions are noted in the code comments. This application requires that call_from is supplied in application_parameters (this is configured on the outbound service page of the CWP). For information on placing outbound calls please read the online web services documentation. For additional information regarding outbound PSTN calls, please see the online documentation. Also have a look at the invoke_outbound_service sample code in the samples_ws directory. """ from prosody.uas import Hangup, Error, FaxToSend, FaxToReceive __uas_identify__ = "application" __uas_version__ = "0.01b" def main(channel, application_instance_id, file_man, my_log, application_parameters, outbound_parameters): try: return_code = 0 # in this sample the call origin and fax header name are given in application_parameters origin, fax_header = application_parameters.split(';') # get the call destination and the fax body name from outbound_parameters destination, fax_body = outbound_parameters.split(';') # This outbound application is going to send a fax, so we create # a FaxToSend object, known as a fax document object my_fax = FaxToSend() # Now set the content of the fax document object, this is read from # a TIFF media file which must be present on the cloud. In this case # the content is a fax header, to which more content will be added. cause = my_fax.set_content(fax_header) # The cause will be of type FileCause and should be checked. if cause != my_fax.FileCause.NORMAL: raise Error("failed to set fax content, cause is {0}".format(cause)) # Add the main fax body to the document. cause = my_fax.append(fax_body) if cause != my_fax.FileCause.NORMAL: raise Error("failed to set fax content, cause is {0}".format(cause)) # Add the page number to each page of the fax document. # First create a PageText object. page_text = my_fax.create_page_text() # We want the page number to be one inch from the top of the page. # So we set the unit of measurement to inches. page_text.Position.unit = page_text.Position.PagePositionUnits.INCHES page_text.Position.from_page_top = 1 # We want the existing line at our pgae number position to be completely removed page_text.mode = page_text.PageTextMode.REPLACE # On each page put the page number on the left for i in range(my_fax.pages_to_send): page_text.left_text = 'This is page {0}'.format(i + 1) # page numbers start a 1 cause = my_fax.add_text_to_page(i + 1, page_text) if cause != my_fax.FileCause.NORMAL: raise Error("failed to set fax content, cause is {0}".format(cause)) # Place the outbound call in the normal way if channel.call(destination, call_from=origin) != channel.State.ANSWERED: cause = channel.cause() raise Error("Call destination returned cause {0}".format(cause)) # Now we can start sending the fax. if channel.FaxSender.start(fax_to_send=my_fax) is not True: cause = channel.FaxSender.cause() raise Error("fax sender failed to start sending the fax, cause is {0}.".format(cause)) # The fax endpoints will negotiate the parameters for the fax session - which modem # and the modem speed, among other things. We can wait until these have been published # and then have a look. Note that the dictionary will be empty if fax negotiation fails. negotiated_settings = channel.FaxSender.wait_for_negotiated_settings() if negotiated_settings == {}: cause = channel.FaxSender.cause() if cause == channel.FaxSender.Cause.NOTFAX: raise Hangup("The receiver was not a fax machine.") else: raise Error("Fax negotiation failed with cause {0}".format(cause)) my_log.debug("Negotiated Settings") for setting, value in negotiated_settings.items(): my_log.debug("{0:>15.15} : {1}".format(setting, value)) # Now we can wait for each page to be sent, we do this until we've been told # that no more pages will be sent. It is important to note that the last_page # flag does not indicate success, it simply means that no more pages will be processed. while channel.FaxSender.Details.last_page is not True: pages = channel.FaxSender.wait_for_next_page() my_log.debug("Sent {0} pages so far".format(pages)) # Now we need to wait until the fax session has finished. We need to do this even though # the last page flag has been set. Remember to check the cause, the last_page indicator # may have been set, but this does not mean that every page was sent. cause = channel.FaxSender.wait_until_finished() if cause != channel.FaxSender.Cause.NORMAL: raise Error("The fax sender failed with cause {0}".format(cause)) # In faxing, it is the receiver that hangs up first, so it is polite # for the fax sender to wait for the other end to hang up. channel.wait_for_idle() except Hangup as exc: my_log.info("Hangup exception reports {0}".format(exc)) return_code = -101 except Error as exc: my_log.error("Error exception reports {0}".format(exc)) return_code = -100 except Exception as exc: my_log.exception("Got unexpected exception {0}".format(exc)) return_code = -102 finally: if channel.state() != channel.State.IDLE: channel.hang_up() return return_code