首先发布这里,所以如果有任何额外的细节是有用的,请告诉我。
我正在尝试从支持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();
}
}
}
我正在努力弄清楚接下来要做什么,以便弄清楚发生了什么,所以任何建议都会非常感激
谢谢
格雷厄姆答案 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;
}