Read out solar inverter - i have working C code - how to use this inside openhab?

Hi,
i have a solarmax 13 mt 3 solar power inverter, which is connected to my network.

I have found some C code which can read out the solar inverter and write the data to a file.

Maybe someone can look at this code and tell me, how i can use this inside openhab? Best thing would be, if i could use this with http-binding or something like this, without the need of this c programm.

Or second best way would be, if this c programm could send the data to openhab (rest api - curl ?) instead of writing it only into a text-file.

Or send the data with MQTT would also be an option.

Is anybody here who can take a short look at this? Here is the code:

I can start the logging with this command:

sudo ./logger 192.168.1.10 12345 test.txt 10
/*
	Simple solarmax logger c program written by zagibu@gmx.ch in August 2010
	This program is licensed under WTFPL 2 http://sam.zoy.org/wtfpl/
	# ./logger hostname port logfile loginterval
	Sources:
		- http://www.linuxhowtos.org/C_C++/socket.htm
		- http://wwwuser.gwdg.de/~kboehm/ebook/21_kap15_w6.html#49329
		- http://man.cx/setbuf%283%29
		- http://www.hinz.fdns.net/timestamp-in-c-and-python.html
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h> 
#include <time.h>
void error(char *msg)
{
	perror(msg);
	exit(0);
}
int main(int argc, char *argv[])
{
	int sockfd, portno, n, log_interval;
	struct sockaddr_in serv_addr;
	struct hostent* server;
	char* message = "{FB;01;46|64:KDY;KMT;KYR;KT0;TNF;TKK;PAC;PRL;IL1;IDC;UL1;UDC;SYS|1199}";
	char buffer[256];
	FILE* file;
	char* file_name;
	char* mode = "a";
	time_t* timestamp;
	// Check commandline arguments
	if (argc < 5)
		error("ERROR program needs hostname, port, logfile and loginterval (in seconds) as parameters");
	// Get log file path from command line argument
	file_name = argv[3];
	// Get log interval from command line argument
	log_interval = atoi(argv[4]);
	// Try to open log file
	if ((file = fopen(file_name, mode)) == NULL)
		error("ERROR opening log file");
	// Make file unbuffered
	setbuf(file, NULL);
	while (1) {
		// Try to open socket
		portno = atoi(argv[2]);
		sockfd = socket(AF_INET, SOCK_STREAM, 0);
		if (sockfd < 0) {
			sleep(60);
			continue;
		}
		// Try to resolve host
		server = gethostbyname(argv[1]);
		if (server == NULL) {
			sleep(60);
			continue;
		}
		// Try to establish a connection
		bzero((char *) &serv_addr, sizeof(serv_addr));
		serv_addr.sin_family = AF_INET;
		bcopy((char *)server->h_addr, 
			(char *)&serv_addr.sin_addr.s_addr,
			server->h_length);
		serv_addr.sin_port = htons(portno);
		if (connect(sockfd,&serv_addr,sizeof(serv_addr)) < 0) {
			sleep(60);
			continue;
		}
		// Start sending the data requests and logging the answers
		while (1) {
			printf("sending message: %s\n", message);
			// Send message 1
			n = write(sockfd,message,strlen(message));
			if (n < 0) 
				break;
			// Read answer
			bzero(buffer, 256);
			n = read(sockfd, buffer, 255);
			if (n < 0) 
				break;
			printf("received answer: %s\n", buffer);
			// Write the current timestamp to file
			timestamp = time(NULL);
			fprintf(file, "NOW=%d;", (int) timestamp);
			// Write the answer data to file
			fprintf(file, "%s;", buffer + 13);
			// Wait for the specified number of seconds
			sleep(log_interval);
		}
	}
	return 0;
}

This c code sends the data with “fprintf” to the file. So how do i have to change this, to send the data with maybe curl to openhab?

With this code i can send data to openhab with the rest api:

curl http://192.168.1.10:8080/classicui/CMD?Dummy_switch=ON

It looks like this uses just plain old sockets. What I can’t tell is if it’s TCP or UDP. But you might be able to experiment with the TCP/UDP binding to reproduce this script. It shouldn’t be too difficult. There isn’t much here. Most of the lines of code here is to write out the reading to file.

C is a very low level programming language. It is not going to easily let you make web calls or anything like that. So your best bet is to do one of the following.

  • Try to implement it with the TCP/UDP Binding and Rules.
  • Try to implement it using JSR223 Rules or with Java inside Rules DSL directly. This C program uses low level socket libraries which will be available to you in either case.
  • Use the LogReader binding to follow the file produced by this C program and update an Item. Set up a .service file so this C program get’s started automatically when the machine reboots.
1 Like

Read a little about sockets som time ago, and believe SOCK_STREAM means it’s TCP :slight_smile:

I think there is some php code which is doing the same too.

Would this help? Is php better readable and usable as c code?

Hi,

I added a script-using approach for getting the data provided by the solar max inverter, today until the SolarMax Binding is finished and released.

It may will fit your sollution: SolarMax (S6000) - Getting data

Best regards