2016-05-07 11 views
2

Azure通知ハブを使用して、Raspberry piからAndroidアプリケーションにプッシュ通知を送信しています。私はこのポストHow to use Notification Hubs from PythonAzure通知ハブ遅延問題

すべてが正常に動作しますが、そこであるごとにREST APIを使用してPythonクライアントアプリを使用しています

、Androidアプリケーションへのラズベリーパイからすべての通知の遅延のほぼ2秒!この遅延を避け、Androidデバイスで同じ秒間に通知を受け取る方法。

私のPythonスクリプト

import time 
import hmac 
import base64 
import hashlib 
import json 
import urllib.parse 
import http.client 


class Notification: 
    def __init__(self, notification_format=None, payload=None, debug=0): 
     valid_formats = ['template', 'apple', 'gcm', 'windows', 'windowsphone', "adm", "baidu"] 
     if not any(x in notification_format for x in valid_formats): 
      raise Exception(
       "Invalid Notification format. " + 
       "Must be one of the following - 'template', 'apple', 'gcm', 'windows', 'windowsphone', 'adm', 'baidu'") 

     self.format = notification_format 
     self.payload = payload 

     # array with keynames for headers 
     # Note: Some headers are mandatory: Windows: X-WNS-Type, WindowsPhone: X-NotificationType 
     # Note: For Apple you can set Expiry with header: ServiceBusNotification-ApnsExpiry 
     # in W3C DTF, YYYY-MM-DDThh:mmTZD (for example, 1997-07-16T19:20+01:00). 
     self.headers = None 


class NotificationHub: 
    API_VERSION = "?api-version=2013-10" 
    DEBUG_SEND = "&test" 

    def __init__(self, connection_string=None, hub_name=None, debug=0): 
     self.HubName = hub_name 
     self.Debug = debug 

     # Parse connection string 
     parts = connection_string.split(';') 
     if len(parts) != 3: 
      raise Exception("Invalid ConnectionString.") 

     for part in parts: 
      if part.startswith('Endpoint'): 
       self.Endpoint = 'https' + part[11:] 
      if part.startswith('SharedAccessKeyName'): 
       self.SasKeyName = part[20:] 
      if part.startswith('SharedAccessKey'): 
       self.SasKeyValue = part[16:] 

    @staticmethod 
    def get_expiry(): 
     # By default returns an expiration of 5 minutes (=300 seconds) from now 
     return int(round(time.time() + 300)) 

    @staticmethod 
    def encode_base64(data): 
     return base64.b64encode(data) 

    def sign_string(self, to_sign): 
     key = self.SasKeyValue.encode('utf-8') 
     to_sign = to_sign.encode('utf-8') 
     signed_hmac_sha256 = hmac.HMAC(key, to_sign, hashlib.sha256) 
     digest = signed_hmac_sha256.digest() 
     encoded_digest = self.encode_base64(digest) 
     return encoded_digest 

    def generate_sas_token(self): 
     target_uri = self.Endpoint + self.HubName 
     my_uri = urllib.parse.quote(target_uri, '').lower() 
     expiry = str(self.get_expiry()) 
     to_sign = my_uri + '\n' + expiry 
     signature = urllib.parse.quote(self.sign_string(to_sign)) 
     auth_format = 'SharedAccessSignature sig={0}&se={1}&skn={2}&sr={3}' 
     sas_token = auth_format.format(signature, expiry, self.SasKeyName, my_uri) 
     return sas_token 

    def make_http_request(self, url, payload, headers): 
     parsed_url = urllib.parse.urlparse(url) 
     connection = http.client.HTTPSConnection(parsed_url.hostname, parsed_url.port) 

     if self.Debug > 0: 
      connection.set_debuglevel(self.Debug) 
      # adding this querystring parameter gets detailed information about the PNS send notification outcome 
      url += self.DEBUG_SEND 
      print("--- REQUEST ---") 
      print("URI: " + url) 
      print("Headers: " + json.dumps(headers, sort_keys=True, indent=4, separators=(' ', ': '))) 
      print("--- END REQUEST ---\n") 

     connection.request('POST', url, payload, headers) 
     response = connection.getresponse() 

     if self.Debug > 0: 
      # print out detailed response information for debugging purpose 
      print("\n\n--- RESPONSE ---") 
      print(str(response.status) + " " + response.reason) 
      print(response.msg) 
      print(response.read()) 
      print("--- END RESPONSE ---") 

     elif response.status != 201: 
      # Successful outcome of send message is HTTP 201 - Created 
      raise Exception(
       "Error sending notification. Received HTTP code " + str(response.status) + " " + response.reason) 

     connection.close() 

    def send_notification(self, notification, tag_or_tag_expression=None): 
     url = self.Endpoint + self.HubName + '/messages' + self.API_VERSION 

     json_platforms = ['template', 'apple', 'gcm', 'adm', 'baidu'] 

     if any(x in notification.format for x in json_platforms): 
      content_type = "application/json" 
      payload_to_send = json.dumps(notification.payload) 
     else: 
      content_type = "application/xml" 
      payload_to_send = notification.payload 

     headers = { 
      'Content-type': content_type, 
      'Authorization': self.generate_sas_token(), 
      'ServiceBusNotification-Format': notification.format 
     } 

     if isinstance(tag_or_tag_expression, set): 
      tag_list = ' || '.join(tag_or_tag_expression) 
     else: 
      tag_list = tag_or_tag_expression 

     # add the tags/tag expressions to the headers collection 
     if tag_list != "": 
      headers.update({'ServiceBusNotification-Tags': tag_list}) 

     # add any custom headers to the headers collection that the user may have added 
     if notification.headers is not None: 
      headers.update(notification.headers) 

     self.make_http_request(url, payload_to_send, headers) 

    def send_apple_notification(self, payload, tags=""): 
     nh = Notification("apple", payload) 
     self.send_notification(nh, tags) 

    def send_gcm_notification(self, payload, tags=""): 
     nh = Notification("gcm", payload) 
     self.send_notification(nh, tags) 

    def send_adm_notification(self, payload, tags=""): 
     nh = Notification("adm", payload) 
     self.send_notification(nh, tags) 

    def send_baidu_notification(self, payload, tags=""): 
     nh = Notification("baidu", payload) 
     self.send_notification(nh, tags) 

    def send_mpns_notification(self, payload, tags=""): 
     nh = Notification("windowsphone", payload) 

     if "<wp:Toast>" in payload: 
      nh.headers = {'X-WindowsPhone-Target': 'toast', 'X-NotificationClass': '2'} 
     elif "<wp:Tile>" in payload: 
      nh.headers = {'X-WindowsPhone-Target': 'tile', 'X-NotificationClass': '1'} 

     self.send_notification(nh, tags) 

    def send_windows_notification(self, payload, tags=""): 
     nh = Notification("windows", payload) 

     if "<toast>" in payload: 
      nh.headers = {'X-WNS-Type': 'wns/toast'} 
     elif "<tile>" in payload: 
      nh.headers = {'X-WNS-Type': 'wns/tile'} 
     elif "<badge>" in payload: 
      nh.headers = {'X-WNS-Type': 'wns/badge'} 

     self.send_notification(nh, tags) 

    def send_template_notification(self, properties, tags=""): 
     nh = Notification("template", properties) 
     self.send_notification(nh, tags) 



isDebug = True 
myConnectionString = "connection string" 
hub = NotificationHub(myConnectionString, "cavenotificationhub", isDebug) 
data = {} 
data['response'] = 'data: R1|X1|S1,1|$' 
json_data = json.dumps(data,separators=(',',':')) 
print(json_data) 
#gcm_payload = {"response":R1|X1|S1,1} 
val= "R1|X1|S1,1|$" 
gcm_payload = { 'data' : {'response': ''+val+''}} 
hub.send_gcm_notification(gcm_payload) 

添付ログ:難しいです

Windows 10 Surface Pro 3 - Python 3.4 script 

**** Send GCM Notitification START> 2016-05-08 10:42:07.883226 
*** make_http_request connection OPEN> 2016-05-08 10:42:08.139328 

--- REQUEST --- 
#Request header 
--- END REQUEST --- 

*** make_http_request START> 2016-05-08 10:42:08.165356 
#Sending request to Azure 
*** make_http_request END> 2016-05-08 10:42:09.016024 

--- RESPONSE --- 
#Response received from Azure 
--- END RESPONSE --- 

*** make_http_request connection CLOSE> 2016-05-08 10:42:09.184785 
**** Send GCM Notitification END> 2016-05-08 10:42:09.188788 

################################################################################################################################ Raspberry Pi Model B+ V1.2 - Python 2.7 script 

('*** Send GCM Notitification START> ', '2016-05-08 10:46:32.692844') ('*** make_http_request connection OPEN> ', '2016-05-08 10:46:32.698456') 

--- REQUEST --- 
#Request header 
--- END REQUEST --- 

('*** make_http_request START> ', '2016-05-08 10:46:32.705946') 
#Sending request to Azure ('*** make_http_request END> ', '2016-05-08 10:46:39.557759') 

--- RESPONSE --- 
#Response received from Azure 
--- END RESPONSE --- 

('*** make_http_request connection CLOSE> ', '2016-05-08 10:46:39.569713') ('*** Send GCM Notitification END> ', '2016-05-08 10:46:39.570986') 

################################################################################################################################ Raspberry Pi 2 Model B V1.1 - Python 2.7 script 

('*** Send GCM Notitification START> ', '2016-05-08 05:36:49.721024') ('*** make_http_request connection OPEN> ', '2016-05-08 05:36:49.732056') 

--- REQUEST --- 
#Request header 
--- END REQUEST --- 

('*** make_http_request START> ', '2016-05-08 05:36:49.733069') 
#Sending request to Azure ('*** make_http_request END> ', '2016-05-08 05:36:50.741605') 

--- RESPONSE --- 
#Response received from Azure 
--- END RESPONSE --- 

('*** make_http_request connection CLOSE> ', '2016-05-08 05:36:50.746248') ('*** Send GCM Notitification END> ', '2016-05-08 05:36:50.747000') 
+0

この質問をお寄せいただきありがとうございます。私は同じ問題に直面しています。通知はAndroidデバイスにも少し遅れて届きます。この問題を解決するのに役立つ人は誰ですか? –

答えて

2

!まず、その問題の原因が何であるかを理解する必要があります。

1)あなたのラズベリーパイ2からバックエンドへのリクエストが長いことがあります。それが問題であるかどうかを理解するには、Service Bus Explorerを使用して、SB名前空間に接続し、通知ハブを開き、Androidペインを選択し、そのペインからプッシュを送信しようとします(スクリーンショットを参照)。通知を速くすると、RPIが何らかの形で関与します。

2)遅れに違いがないことがわかり、RPIまたはSBを使用して通知を送信して2-3秒後にプッシュした場合は、絶対に問題ないと言います。例えば、See that topicである。実際には多くの要素に依存しており、時間を短縮しようとしたとき(時には5〜10秒を観測)、多くの問題はクライアントまたはブローカー(NHの場合)ではなく、通知プラットフォームであることがわかりました。

もちろん、通知を同じ秒間に配信するとは限りません。我々が持っていたベスト - 2秒後またはそれ以降。しかし、それは本当に保証されていません。

+0

お返事ありがとうございました@Alex。私たちは3つの異なるプラットフォームでテストを行い、ログはOPに添付されています。タイムスタンプごとに、私たちはRaspberry Pi Model B + V1.2で約6秒の遅延(約1-2秒の遅延が許容されます)を得ています。あなたはこの遅れを減らす方法についてのあなたの洞察を共有していただけますか? –

+1

@SatishGunjal私は究極の真実を知っているとは言えません。私の過去の経験によれば、平均レイテンシを減らすために多くのことはありません。どうやら、遅延は最大10分である可能性があります。これらのスレッドを参照してください - http://stackoverflow.com/questions/9204767/how-much-delay-of-ios-push-notification and http://stackoverflow.com/questions/19560448/how-to-avoid-delay- in-android-gcm-messages-change-heartbeatと入力します。あなたはAndroidの質問から技術を実装しようとするかもしれませんが、それがどのようになっているかを見てください。 –

+0

即座に通知を届ける安定したメカニズムをご希望の場合は、「保証されていない」性質のため、プッシュは間違った選択です。通知のカスタム実装を検討しましたか? –

関連する問題