以最少的数据使用推送通知

Push notifications with minimal data usage

在我的项目中,我想从 Internet 调用对 Raspberry Pi 的操作。有点像这样:

  1. 访问网页
  2. 点击网页上的按钮
  3. Raspberry pi 执行脚本

困难的部分是 raspberry pi 只有移动互联网连接 没有统一费率 。因此,发送和接收数据 from/to Raspberry Pi 是昂贵的。

所以这是我的问题:

我可以使用哪些技术和模式将推送通知发送到 raspberry pi ,同时使用最少的数据

首先在 RPi 上创建或启动接受传入连接的东西。像下面的例子那样的小东西:

#!/usr/bin/python
from socket import *
s = socket()
s.bind(('', 8001))
s.listen(4)
while 1:
    ns, na = s.accept()
    print(na,'sent you:',ns.recv(8192))

现在,上面的例子只会在 8001 上打开一个端口,然后打印其他发送给它的任何内容。

在服务器端,我建议您设置一个 Web 服务器或其他易于访问的东西,可以将 IP 存储在 database/register 某处。

然后,在你的树莓派启动期间(首选在网络服务启动之后)继续并安排:

curl https://your-server.eu/reg_ip.php > /dev/null 2>&1

现在,在服务器 your-server.eu:443 上,确保 req_ip.php 将客户端 IP(客户端是您的 RPi)保存在某个数据库中。

现在,您需要发送 PUSH 通知的任何应用程序都可以在数据库中查找客户端的当前 IP 并尝试连接到这些 IP 上的端口 8001 并发送您需要的任何数据.

现在有两件事:

  1. 侦听 TCP 套接字(在 RPi 上)根本不会用完任何数据,但会在需要时允许传入连接。

  2. 如果您的 RPi 上的 IP 发生变化(例如,它可能会在移动的 GSM/3G/4G 网络上发生变化),您需要向服务器发送另一个 curl 请求。然而,这可以很容易地绑定到例如 ip monitor 命令,然后执行 curl 请求。

tl;博士

这是您的链条:

Pi opens a listening socket -> Pi connects to HTTP(S) -> servers saves IP -> when server has something to send -> connect to last known IP on port X -> send data -> close connection

进一步加强

现在,单独的 HTTP header 就相当大了,实际上它是默认的 78 字节包数据(TCP 和 IP headers 通常不包括在数据速率中,只有数据正在传输的是 - 在本例中为 HTTP 数据。)。所以你可以扩展的是,如果你也可以在服务器上使用上面的简单套接字示例,只需获取 na[0] 变量并将其发送到数据库,这样你就可以直接使用 0 data-rate 在您的数据订阅上。

只有稍后从服务器应用程序作为 "PUSH notification" 发送的实际数据才会用完数据。

如果您的树莓派位于基于 NAT 的网络(专用网络)上

看到 OP 获得了一个 10.X.X.X 地址,侦听套接字不太可能做到这一点。

相反,您可以做的是简单地尝试建立连接并保持连接打开,并让服务器在有数据时通过任何打开的套接字发送数据。

这里有一个关于如何实现它的非常粗略的想法。
我保持简单和愚蠢只是为了提供一个想法而没有解决整个问题。

同样,在您实际通过通道发送数据之前,客户端 (RPi) 和服务器之间的开放套接字不会用完任何数据。

您可以在服务器中从数据库中获取要发送给客户端的数据,您真的可以做任何事情。由于我不知道你的目标,所以我暂时保持原样。

服务器:

#!/usr/bin/python
from socket import *
from threading import *
from time import time, sleep
from random import randint

class ClientThread(Thread)
    def __init__(self, clients):
        self.clients = clients
        self.messages = []
        Thread.__init__(self)
        self.start()

    def notify(self, message):
        if type(message) is str: message = bytes(message, 'UTF-8')
        self.messages.append(message)

    def run(self):
        while 1:
            if len(self.messages) > 0:
                m = self.messages.pop(0)
                for client in self.clients:
                    self.clients[client]['sock'].send(m)

class RandomMessageGenerator(Thread):
    def __init__(self, notify_func):
        self.notify_func = notify_func
        self.last = time()
        Thread.__init__(self)
        self.start()

    def run(self):
        while 1:
            self.notify_func('Time since last update: ' + str(time() - self.last))
            self.last = time()
            sleep(randint(0,30))

client_list = {}
client_thread_handle = ClientThread(client_list)
random_generator = RandomMessageGenerator(client_thread_handle.nofity)

s = socket()
s.bind(('', 8001))
s.listen(4)

while 1:
    ns, na = s.accept()
    client_list[na] = {'sock' : 'ns'}

客户:

from socket import *
s = socket()
s.connect(('server', 8001))
while 1:
    print(s.recv(8192))