Как отправить push-уведомление с помощью Erlang?
Я пытаюсь отправить push-уведомление для APN, используя Erlang.
Это код, который я придумал до сих пор:
-module(apnstest2).
-export([connect/0]).
connect() ->
application:start(ssl),
ssl:seed("someseedstring"),
Address = "gateway.sandbox.push.apple.com",
Port = 2195,
Cert = "/path/to/Certificate.pem",
Key = "/path/to/Key.unenc.pem",
Options = [{certfile, Cert}, {keyfile, Key}, {mode, binary}],
Timeout = 1000,
{ok, Socket} = ssl:connect(Address, Port, Options, Timeout),
Token = "195ec05a962b24954693c0b638b6216579a0d1d74b3e1c6f534c6f8fd0d50d03",
Payload = "{\"aps\":{\"alert\":\"Just testing.\",\"sound\":\"chime\", \"badge\":10}}",
TokenLength = length(Token),
PayloadLength = length(Payload),
Packet = [<<0:8, TokenLength, Token, PayloadLength, Payload>>],
ssl:send(Socket, list_to_binary(Packet)),
ssl:close(Socket).
Код не использует Erlang concurrency, а просто прототип. Я только хочу проверить, могу ли я отправить push самым простым способом.
Я думаю, что проблема заключается в том, что пакет отправляется в APN.
Это двоичный формат push-уведомления:
alt text http://developer.apple.com/IPhone/library/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Art/aps_provider_binary.jpg
Как создать такой пакет в Erlang?
Может кто-нибудь, пожалуйста, взгляните на мой код и скажите мне, где проблема?
Также я использовал приложение Erlang SSL для создания соединения и отправки данных, и я не знаю, является ли это проблемой или пакетом.
Спасибо!
Ответы
Ответ 1
Для начала нет необходимости создавать список одного двоичного кода, а затем вызывать list_to_binary/1
на нем. Вы можете просто отправить сам файл.
Кроме того, убедитесь, что длины полей и значения соответствуют протоколу:
TokenLength = 32 = length(Token),
Packet = <<0:8, TokenLength:16/big, Token, PayloadLength:16/big, Payload>>,
ssl:send(Socket, Packet),
Теперь, когда мы достигли этого, мы увидим, что длина (токен) на самом деле равна 64, а не 32:
Вы забыли преобразовать шестнадцатеричную строку для Token в двоичный файл, поэтому вы отправляете шестнадцатеричную шестнадцатеричную символьную строку вместо 32 двоичных байтов.
Итак... сделав полезную нагрузку двоичным с самого начала и сделав Token числовой константой, вы можете сделать что-то вроде следующего:
Payload = <<"{\"aps\":{\"alert\":\"Just testing.\",\"sound\":\"chime\", \"badge\":10}}">>,
PayloadLength = size(Payload),
Packet = <<0:8, 32:16/big,
16#195ec05a962b24954693c0b638b6216579a0d1d74b3e1c6f534c6f8fd0d50d03:256/big,
PayloadLength:16/big, Payload/binary>>,
ssl:send(Socket, Packet),
Благодаря Christian для указания ряда ошибок в предыдущих версиях этого ответа.
Ответ 2
Я вижу две ошибки:
- Токен должен быть передан двоичным, а не шестнадцатеричным ascii.
- Вы не можете использовать бинарный синтаксис для преобразования списков в двоичные файлы.
Для разбора шестнадцатеричного целого числа, а затем до двоичного кода используйте что-то вроде этого:
Token = "dead",
TokenNum = erlang:list_to_integer(Token, 16),
TokenBin = <<TokenNum:32/integer-unit:8>>,
Создайте пакет протокола с чем-то вроде этого:
TokenBin = ...,
Payload = <<"Payload">>,
PayloadSize = byte_size(Payload),
Packet = <<0:8, 32:16, TokenBin/binary, PayloadSize:16, Payload/binary>>,
Ответ 3
Попробуйте использовать простую библиотеку epns (Erlang Push Notifications)
Эта библиотека может отправлять push-уведомления в виде APNS и FCM на стороне Erlang. Как использовать библиотеку epns(Erlang Push Notifications) - вы можете прочитать в README.md. Эта библиотека может использоваться как сторонняя организация в проекте, или вы можете запустить ее локально, чтобы посмотреть, как работает эта библиотека:
$ git clone https://github.com/vkatsuba/epns.git
$ cd epns
$ make
Проверено на Erlang 20 ~ 21