从太阳能逆变器,UDP广播中提取数据?

时间:2016-08-07 08:27:00

标签: android python udp broadcast

首先发布这里,所以如果有任何额外的细节是有用的,请告诉我。

我正在尝试从支持WiFi的太阳能光伏逆变器中提取数据(例如,发电与时间,今天产生的能量,电池充电水平等)。 在Playstore中有一个名为kstarmg的Android应用程序,它已经完成了一些但仅在连接到本地网络时才有效,因此无法通过Internet访问。我想写一些东西在本地机器(raspberry pi)上运行,它从逆变器记录数据并更新网页。我的第一个想法是使用python。

我设法反编译android app apk,据我所知它使用UDP广播与逆变器通信。到目前为止,我可以看到它在端口48899上发送了一些文本“WIFIKIT-214028-READ”。我已经设法通过在树莓派上使用nc来监听这个文本。我正在努力研究如何读取逆变器的响应。谁能指出我如何确定如何从逆变器读取数据?

我在python中尝试了以下内容但没有得到任何回复:

import socket
import struct

import sys
message = 'WIFIKIT-214028-READ'
multicast_group = ('224.3.29.71', 48899)
# Create the datagram socket                                                                                     sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# Set a timeout so the socket does not block indefinitely when trying to receive data.
sock.settimeout(20)
# Set the time-to-live for messages to 1 so they do not go past the local network segment.                       ttl = struct.pack('b', 1)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, ttl)                                                 
try:
    # Send data to the multicast group
    print >>sys.stderr, 'sending "%s"' % message                                                                     sent = sock.sendto(message, multicast_group)
    # Look for responses from all recipients                                                                         while True:
        print >>sys.stderr, 'waiting to receive'
        try:
            data, server = sock.recvfrom(16)
        except socket.timeout:
            print >>sys.stderr, 'timed out, no more responses'                                                               break
        else:
            print >>sys.stderr, 'received "%s" from %s' % (data, server)
finally:                                                                                                             print >>sys.stderr, 'closing socket'
    sock.close()

android apk中的一些似乎相关的行是:

package com.kstar.common;

import android.util.Log;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public abstract class UdpBroadcast {
    private static final int BUFFER_SIZE = 100;
    private static final String TAG = "UdpBroadcast";
    private InetAddress inetAddress;
    private DatagramPacket packetToSend;
    private int port;
    private ReceiveData receiveData;
    private DatagramSocket socket;

    /* renamed from: com.kstar.common.UdpBroadcast.1 */
    class C00521 extends Thread {
        C00521() {
        }

        public void run() {
            DatagramPacket packet = new DatagramPacket(new byte[UdpBroadcast.BUFFER_SIZE], UdpBroadcast.BUFFER_SIZE);
            long time = System.currentTimeMillis();
            while (System.currentTimeMillis() - time < 300) {
                try {
                    UdpBroadcast.this.socket.receive(packet);
                } catch (Exception e) {
                }
            }
            try {
                Log.i(UdpBroadcast.TAG, "--UdpBroadcast Send:  ------------>" + new SimpleDateFormat("hh:mm:ss").format(new Date()));
                UdpBroadcast.this.socket.setSoTimeout(1000);
                UdpBroadcast.this.socket.send(UdpBroadcast.this.packetToSend);
            } catch (IOException e2) {
                e2.printStackTrace();
            }
            UdpBroadcast.this.receiveData = new ReceiveData(null);
            Log.i(UdpBroadcast.TAG, "--UdpBroadcast receiveData:  ------------>" + new SimpleDateFormat("hh:mm:ss").format(new Date()));
            UdpBroadcast.this.receiveData.start();
        }
    }

    private class ReceiveData implements Runnable {
        private List<DatagramPacket> packets;
        private boolean stop;
        private Thread thread;

        private ReceiveData() {
            this.thread = new Thread(this);
            this.packets = new ArrayList();
        }

        public void run() {
            this.stop = false;
            while (!this.stop) {
                try {
                    DatagramPacket packetToReceive = new DatagramPacket(new byte[UdpBroadcast.BUFFER_SIZE], UdpBroadcast.BUFFER_SIZE);
                    UdpBroadcast.this.socket.receive(packetToReceive);
                    this.packets.add(packetToReceive);
                } catch (SocketTimeoutException e) {
                } catch (Exception e2) {
                    e2.printStackTrace();
                }
            }
            if (!this.stop) {
                UdpBroadcast.this.onReceived(this.packets);
            }
            this.stop = true;
        }

        void start() {
            this.thread.start();
        }

        void stop() {
            this.stop = true;
        }

        boolean isStoped() {
            return this.stop;
        }
    }

    public abstract void onReceived(List<DatagramPacket> list);

    public void setPort(int port) {
        this.port = port;
    }

    public UdpBroadcast() {
        this.port = Constant.UDP_PORT;
        this.socket = null;
        try {
            this.inetAddress = InetAddress.getByName("255.255.255.255");
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
    }

    public void open() {
        try {
            if (this.socket == null) {
                this.socket = new DatagramSocket(this.port);
                this.socket.setBroadcast(true);
            }
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }

    public void close() {
        stopReceive();
        if (this.socket != null) {
            this.socket.close();
            this.socket = null;
        }
    }

    public void send(String text) {
        if (this.socket != null && text != null) {
            text = text.trim();
            this.packetToSend = new DatagramPacket(text.getBytes(), text.getBytes().length, this.inetAddress, this.port);
            try {
                this.socket.setSoTimeout(500);
                stopReceive();
                new C00521().start();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public void stopReceive() {
        if (this.receiveData != null && !this.receiveData.isStoped()) {
            this.receiveData.stop();
        }
    }
}

我正在努力弄清楚接下来要做什么,以便弄清楚发生了什么,所以任何建议都会非常感激

谢谢

格雷厄姆

1 个答案:

答案 0 :(得分:0)

为了改变逆变器上的计时器,我设法用 PHP 做到了,也许这会有所帮助。 首先,我安装了一个数据包嗅探器(我使用了 HttpCanary)来查找更改计时器的命令。 例如,“AA55B07F02390B0701040E00173BFFF1FF7F064E”会将第一个计时器设置为 14:00。 我使用了以下函数,其中大部分来自 here

function send_socket(){
$server = '137.134.128.220';
$port = 13435;
$return="Not OK";
if(!($sock = socket_create(AF_INET, SOCK_DGRAM, 0))){
    $errorcode = socket_last_error();
    $errormsg = socket_strerror($errorcode);
    $return="Couldn't create socket: [$errorcode] $errormsg";
    return $return;
}
$return="Socket created";

$output = hex2bin("AA55B07F02390B0701040E00173BFFF1FF7F064E");//start at 2


//Send the message to the server
if( ! socket_sendto($sock, $output , strlen($output) , 0 , $server , $port)){
    $errorcode = socket_last_error();
    $errormsg = socket_strerror($errorcode);
    $return="Could not send data: [$errorcode] $errormsg";
    return $return;
}

//Now receive reply from server and print it
if(socket_recv ( $sock , $reply , 2045 , MSG_WAITALL ) === FALSE){
    $errorcode = socket_last_error();
    $errormsg = socket_strerror($errorcode);
    $return="Could not receive data: [$errorcode] $errormsg";
    return $return;
}

$return=bin2hex($reply);
echo "Reply: $return";
if ($return=="aa557fb002b9010602f0"){
    $return="Success";
}
return $return;
}