01234567890123456789012345678901234567890123456789012345678901234567890123456789
6426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522 66896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729 | <----SKIPPED LINES----> % subscription_id) curl.setopt(pycurl.HTTPHEADER, [ 'X-Vestaboard-Api-Key:%s' % key, 'X-Vestaboard-Api-Secret:%s' % secret]) curl.setopt(pycurl.TIMEOUT_MS, timeout*1000) curl.setopt(pycurl.POST, 1) curl.setopt(pycurl.WRITEFUNCTION, lambda x: None) # to keep stdout clean # preparing body the way pycurl.READDATA wants it body_as_dict = {'characters': StringToCharArray(s)} body_as_json_string = json.dumps(body_as_dict) # dict to json body_as_file_object = io.StringIO(body_as_json_string) # prepare and send. See also: pycurl.READFUNCTION to pass function instead curl.setopt(pycurl.READDATA, body_as_file_object) curl.setopt(pycurl.POSTFIELDSIZE, len(body_as_json_string)) web_publish_failure_msg = '' try: curl.perform() status_msg = 'Web service published' status_code = 'SUCCESS' except pycurl.error as e: timing_message = CurlTimingDetailsToString(curl) web_publish_failure_msg = ( 'curl.perform() failed with message %s; timing details: %s' % (e, timing_message)) # Using the remote webservice failed, but maybe the local API will # be more successful? If this succeeds, then we should not indicate # a failure on the status light / dashboard, but we should still log # the remote failure Log(web_publish_failure_msg) local_publish_error_msg = PublishMessageLocal( s, timeout=timeout, update_dashboard=False) if not local_publish_error_msg: status_msg = ( 'Local service published (1) because web service failed with %s' % web_publish_failure_msg) status_code = 'WARNING' else: status_msg = ( 'Local service failed (2) with %s after web service failed with %s' % (local_publish_error_msg, web_publish_failure_msg)) status_code = 'FAIL' else: # you may want to check HTTP response code, e.g. timing_message = CurlTimingDetailsToString(curl) status_code = curl.getinfo(pycurl.RESPONSE_CODE) if status_code != 200: web_publish_failure_msg = ( 'Server returned HTTP status code %d for message %s; ' 'timing details: %s' % (status_code, s, timing_message)) Log(web_publish_failure_msg) local_publish_error_msg = PublishMessageLocal( s, timeout=timeout, update_dashboard=False) if not local_publish_error_msg: status_msg = ( 'Local service published (3) because web service failed with %s' % web_publish_failure_msg) status_code = 'WARNING' else: status_msg = ( 'Local service failed (4) with %s after web service failed with %s' % (local_publish_error_msg, web_publish_failure_msg)) status_code = 'FAIL' # We've logged the error code from the external web service, but the # Vestaboard local API was able to recover from the error, so we need not # log the failure message / error code in the dashboard. if not error_code: web_publish_failure_msg = '' curl.close() UpdateStatusLight( GPIO_ERROR_VESTABOARD_CONNECTION, status_code=='FAIL', web_publish_failure_msg) return status_msg, status_code def PublishMessageLocal( s, local_key=LOCAL_KEY, local_address=LOCAL_VESTABOARD_ADDRESS, timeout=5, update_dashboard=True): """Publishes a text string to a Vestaboard via local API. The message is pushed to the vestaboard splitflap display by way of its local API; see https://docs.vestaboard.com/local for more details. Args: s: String to publish. local_key: string key from Vestaboard for local API access. local_address: the address and port to the local Vestaboard service. timeout: Max duration in seconds that we should wait to establish a connection. update_dashboard: Boolean indicating whether this method should update the <----SKIPPED LINES----> for message in messages_to_display: # we cannot just unpack the tuple because messages of type # FLAG_MSG_FLIGHT & FLAG_MSG_INSIGHT are 3-tuples (with the third # element being the flight dictionary) whereas other message types # are 2-tuples message_type = message[0] message_text = message[1] # There may be one or several insight messages that were added to the # message queue along with the flight at a time when the screen was # enabled, but by the time it comes to display them, the screen is now # disabled. These should not be displayed. Note that this check only # needs to be done for insight messages because other message types # are user initiated and so presumably should be displayed irrespective # of when the user triggered it to be displayed. if message_type == FLAG_MSG_INSIGHT and not MessageMeetsDisplayCriteria( configuration): publish_status_msg = ( 'Message purged as no longer meets display criteria') publish_status_code = 'WARN' Log('Message %s purged' % message_text) else: if isinstance(message_text, str): message_text = textwrap.wrap( message_text, width=SPLITFLAP_CHARS_PER_LINE) display_message = Screenify(message_text, False) Log(display_message, file=ALL_MESSAGE_FILE) # Saving this to disk allows us to identify # persistently whats currently on the screen PickleObjectToFile(message, PICKLE_SCREENS, True) screens.append(message) MaintainRollingWebLog(display_message, 25) if not SIMULATION: splitflap_message = Screenify(message_text, True) publish_status = PublishMessageWeb(splitflap_message) publish_status_msg, publish_status_code = publish_status <----SKIPPED LINES----> |
01234567890123456789012345678901234567890123456789012345678901234567890123456789
6426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522 66896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729 | <----SKIPPED LINES----> % subscription_id) curl.setopt(pycurl.HTTPHEADER, [ 'X-Vestaboard-Api-Key:%s' % key, 'X-Vestaboard-Api-Secret:%s' % secret]) curl.setopt(pycurl.TIMEOUT_MS, timeout*1000) curl.setopt(pycurl.POST, 1) curl.setopt(pycurl.WRITEFUNCTION, lambda x: None) # to keep stdout clean # preparing body the way pycurl.READDATA wants it body_as_dict = {'characters': StringToCharArray(s)} body_as_json_string = json.dumps(body_as_dict) # dict to json body_as_file_object = io.StringIO(body_as_json_string) # prepare and send. See also: pycurl.READFUNCTION to pass function instead curl.setopt(pycurl.READDATA, body_as_file_object) curl.setopt(pycurl.POSTFIELDSIZE, len(body_as_json_string)) web_publish_failure_msg = '' try: curl.perform() status_msg = 'Web service published' publish_status_code = 'SUCCESS' except pycurl.error as e: timing_message = CurlTimingDetailsToString(curl) web_publish_failure_msg = ( 'curl.perform() failed with message %s; timing details: %s' % (e, timing_message)) # Using the remote webservice failed, but maybe the local API will # be more successful? If this succeeds, then we should not indicate # a failure on the status light / dashboard, but we should still log # the remote failure Log(web_publish_failure_msg) local_publish_error_msg = PublishMessageLocal( s, timeout=timeout, update_dashboard=False) if not local_publish_error_msg: status_msg = ( 'Local service published (1) because web service failed with %s' % web_publish_failure_msg) publish_status_code = 'WARNING' else: status_msg = ( 'Local service failed (2) with %s after web service failed with %s' % (local_publish_error_msg, web_publish_failure_msg)) publish_status_code = 'FAILURE' else: # you may want to check HTTP response code, e.g. timing_message = CurlTimingDetailsToString(curl) status_code = curl.getinfo(pycurl.RESPONSE_CODE) if status_code != 200: web_publish_failure_msg = ( 'Server returned HTTP status code %d for message %s; ' 'timing details: %s' % (status_code, s, timing_message)) Log(web_publish_failure_msg) local_publish_error_msg = PublishMessageLocal( s, timeout=timeout, update_dashboard=False) if not local_publish_error_msg: status_msg = ( 'Local service published (3) because web service failed with %s' % web_publish_failure_msg) publish_status_code = 'WARNING' else: status_msg = ( 'Local service failed (4) with %s after web service failed with %s' % (local_publish_error_msg, web_publish_failure_msg)) publish_status_code = 'FAILURE' # We've logged the error code from the external web service, but the # Vestaboard local API was able to recover from the error, so we need not # log the failure message / error code in the dashboard. if not error_code: web_publish_failure_msg = '' curl.close() UpdateStatusLight( GPIO_ERROR_VESTABOARD_CONNECTION, publish_status_code=='FAILURE', web_publish_failure_msg) return status_msg, publish_status_code def PublishMessageLocal( s, local_key=LOCAL_KEY, local_address=LOCAL_VESTABOARD_ADDRESS, timeout=5, update_dashboard=True): """Publishes a text string to a Vestaboard via local API. The message is pushed to the vestaboard splitflap display by way of its local API; see https://docs.vestaboard.com/local for more details. Args: s: String to publish. local_key: string key from Vestaboard for local API access. local_address: the address and port to the local Vestaboard service. timeout: Max duration in seconds that we should wait to establish a connection. update_dashboard: Boolean indicating whether this method should update the <----SKIPPED LINES----> for message in messages_to_display: # we cannot just unpack the tuple because messages of type # FLAG_MSG_FLIGHT & FLAG_MSG_INSIGHT are 3-tuples (with the third # element being the flight dictionary) whereas other message types # are 2-tuples message_type = message[0] message_text = message[1] # There may be one or several insight messages that were added to the # message queue along with the flight at a time when the screen was # enabled, but by the time it comes to display them, the screen is now # disabled. These should not be displayed. Note that this check only # needs to be done for insight messages because other message types # are user initiated and so presumably should be displayed irrespective # of when the user triggered it to be displayed. if message_type == FLAG_MSG_INSIGHT and not MessageMeetsDisplayCriteria( configuration): publish_status_msg = ( 'Message purged as no longer meets display criteria') publish_status_code = 'WARNING' Log('Message %s purged' % message_text) else: if isinstance(message_text, str): message_text = textwrap.wrap( message_text, width=SPLITFLAP_CHARS_PER_LINE) display_message = Screenify(message_text, False) Log(display_message, file=ALL_MESSAGE_FILE) # Saving this to disk allows us to identify # persistently whats currently on the screen PickleObjectToFile(message, PICKLE_SCREENS, True) screens.append(message) MaintainRollingWebLog(display_message, 25) if not SIMULATION: splitflap_message = Screenify(message_text, True) publish_status = PublishMessageWeb(splitflap_message) publish_status_msg, publish_status_code = publish_status <----SKIPPED LINES----> |