Voici celui que j'utilise (fait à partir de celui que tu recherches).
Il faut lui passer, en arguments, l'url à appeler pour mettre à jour domoticz, avec les idx des 3 widgets.
Code : Tout sélectionner
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <limits.h>
#include <sys/time.h>
#include <curl/curl.h>
// On va passer en parametres:
// - l'url json du serveur Domoticz
// - l'idx Domoticz du smartmeter
// - l'idx du suivi courant tri-phasé (de type Current,CM113 Electrisave)
// - l'idx du switch HC/HP
//--------------------------------------------------
// DONNEES A MODIFIER EN FONCTION DE LA CONFIGURATION SOUHAITEE
//--------------------------------------------------
// Port Serie et Baud Rate
// Délimiteur (normalement 0x09 à 9600 bauds et 0x20 à 1200 bauds)
// Requête JSON pour Domoticz (CHANGER LE IDX AVEC LE NUMERO DE DEVICE)
//--------------------------------------------------
const char* SERIAL_PORT = "/dev/ttyUSBTINFO";
const speed_t BAUD_RATE = B9600;
const char DEMILITER = 0x09;
//const char* JSON_HEADER = "http://192.168.1.23:8080/json.htm?type=command¶m=udevice&idx=804&nvalue=0&svalue=";
char JSON_HEADER[1024]; // = "http://192.168.1.23:8080/json.htm?type=command¶m=udevice&idx=804&nvalue=0&svalue=";
//--------------------------------------------------
/* Number of consecutive characters to read (max = 255) */
const unsigned int BUFFER_SIZE = 255;
/* Max number of characters in one line (<= BUFFER SIZE) */
const unsigned int MAX_LINE_SIZE = 150;
/* Min number of characters in one line (<= MAX_LINE_SIZE) */
const unsigned int MIN_LINE_SIZE = 5;
typedef struct {
unsigned int EAST;
unsigned int EAIT;
unsigned int SINSTS;
unsigned int SINSTI;
unsigned int EASF01;
unsigned int EASF02;
unsigned int IRMS1;
unsigned int IRMS2;
unsigned int IRMS3;
unsigned int TARIF;
} Teleinfo;
typedef struct {
int value;
unsigned int elapsed_seconds;
} DomoticzDevice;
Teleinfo teleinfo = { .EAST = 0, .EAIT = 0, .SINSTS = 0, .SINSTI = 0, .EASF01 = 0, .EASF02 = 0, .IRMS1 = 0, .IRMS2 = 0, .IRMS3 = 0, .TARIF = 0 };
DomoticzDevice EDF = { .value = 0, .elapsed_seconds = 0 };
unsigned int send_message = 0;
struct timeval tv1; struct timezone tz1;
struct timeval tv2; struct timezone tz2;
int set_interface_attribs(int fd, int speed)
{
struct termios tty;
if (tcgetattr(fd, &tty) < 0)
{
printf("Error from tcgetattr: %s\n", strerror(errno));
return -1;
}
cfsetospeed(&tty, (speed_t)speed);
cfsetispeed(&tty, (speed_t)speed);
tty.c_cflag |= (CLOCAL | CREAD); /* ignore modem controls */
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS7; /* 7-bit characters */
tty.c_cflag |= PARENB; /* parity enabled & even */
tty.c_cflag &= ~CSTOPB; /* 1 stop bit */
tty.c_cflag &= ~CRTSCTS; /* no hardware flowcontrol */
/* setup for non-canonical mode */
tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
tty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
tty.c_oflag &= ~OPOST;
/* read characters, with max delay of half second to receive a char */
tty.c_cc[VMIN] = BUFFER_SIZE;
tty.c_cc[VTIME] = 5;
if (tcsetattr(fd, TCSANOW, &tty) != 0)
{
printf("Error from tcsetattr: %s\n", strerror(errno));
return -1;
}
return 0;
}
int isCheckSumOk(char* line)
{
unsigned int checksum_expected = 0;
unsigned int checksum_real = 0;
unsigned int i;
checksum_expected = line[strlen(line) - 1];
for (i = 0; i <= strlen(line) - 2; i++)
{
checksum_real += line[i];
}
checksum_real = (checksum_real & 0x3F) + 0x20;
if (checksum_expected != checksum_real)
{
//printf("ERROR --> Checksum failed on line: \"%s\"\n", line);
unsigned char *p;
unsigned int linelen = strlen(line);
for (p = line; linelen-- > 0; p++)
//printf(" 0x%x", *p);
//printf("\n");
return -1;
}
return 0;
}
int strToUL(char* str)
{
unsigned int val = 0;
char *endptr;
errno = 0;
val = strtoul(str, &endptr, 10);
if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) || (errno != 0 && val == 0))
{
printf("ERROR --> Cannot convert to ul the string: \"%s\"\n", str);
return -1;
}
else if (endptr == str)
{
printf("ERROR --> Cannot convert to ul an empty string: \"%s\"\n", str);
return -1;
}
return (int)val;
}
int sendUrl(char* url)
{
int ret = -1;
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if (curl)
{
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); //Prevent "longjmp causes uninitialized stack frame" bug
curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "deflate");
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60);
//curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
//curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data);
res = curl_easy_perform(curl);
if(res != CURLE_OK)
{
printf("ERROR --> Cannot send curl url: \"%s\"\n", url);
}
else
{
ret = 0;
}
curl_easy_cleanup(curl);
}
else
{
printf("ERROR --> Cannot init curl\n");
}
return ret;
}
int processLine(char* line)
{
char label [MAX_LINE_SIZE];
char elem1 [MAX_LINE_SIZE];
char elem2 [MAX_LINE_SIZE];
int val;
unsigned int start = 0;
unsigned int i = 0;
// Find next elem
label[0] = '\0';
for (i = start; i <= strlen(line) - 2; i++)
{
// Find the delimiter
if (line[i] == DEMILITER)
{
memcpy(label, &line[start], i-start);
label[i-start] = '\0';
break;
}
}
// Find next elem
start = i+1;
elem1[0] = '\0';
for (i = start; i <= strlen(line) - 2; i++)
{
// Find the delimiter
if (line[i] == DEMILITER)
{
memcpy(elem1, &line[start], i-start);
elem1[i-start] = '\0';
break;
}
}
// Find next elem
start = i+1;
elem2[0] = '\0';
for (i = start; i <= strlen(line) - 2; i++)
{
// Find the delimiter
if (line[i] == DEMILITER)
{
memcpy(elem2, &line[start], i-start);
elem2[i-start] = '\0';
break;
}
}
printf("DEBUG --> New line: %s - %s - %s\n", label, elem1, elem2);
// Save value
if(strcmp(label, "EAST") == 0) {
val = strToUL(elem1);
if (val != -1) teleinfo.EAST = (unsigned int)val;
else return -1;
} else
if(strcmp(label, "EAIT") == 0) {
val = strToUL(elem1);
if (val != -1) teleinfo.EAIT = (unsigned int)val;
else return -1;
}
else if(strcmp(label, "SINSTS") == 0) {
val = strToUL(elem1);
if (val != -1) teleinfo.SINSTS = (unsigned int)val;
else return -1;
}
else if(strcmp(label, "SINSTI") == 0) {
val = strToUL(elem1);
if (val != -1) teleinfo.SINSTI = (unsigned int)val;
else return -1;
}
if(strcmp(label, "IRMS1") == 0) {
val = strToUL(elem1);
if (val != -1) teleinfo.IRMS1 = (unsigned int)val;
else return -1;
} else
if(strcmp(label, "IRMS2") == 0) {
val = strToUL(elem1);
if (val != -1) teleinfo.IRMS2 = (unsigned int)val;
else return -1;
} else
if(strcmp(label, "IRMS3") == 0) {
val = strToUL(elem1);
if (val != -1) teleinfo.IRMS3 = (unsigned int)val;
else return -1;
} else
if(strcmp(label, "NTARF") == 0) {
val = strToUL(elem1);
if (val != -1) teleinfo.TARIF = (unsigned int)val;
else return -1;
} else
if(strcmp(label, "EASF01") == 0) {
val = strToUL(elem1);
if (val != -1) teleinfo.EASF01 = (unsigned int)val;
else return -1;
} else
if(strcmp(label, "EASF02") == 0) {
val = strToUL(elem1);
if (val != -1) teleinfo.EASF02 = (unsigned int)val;
else return -1;
}
}
int main(int argc, char * argv[])
{
//freopen("out.txt", "a", stdout);
int fd;
int wlen;
int i;
unsigned char line[MAX_LINE_SIZE];
unsigned int linelen = 0;
unsigned int pos = 0;
if(argc < 4)
{
printf("Usage: url json du domoticz à alimenter\r\n");
printf(" idx du smartmeter\r\n");
printf(" idx du suivi courant tri-phasé\r\n");
printf(" idx du switch HC/HP");
exit(0);
}
for(i = 0 ; i< argc ; i ++)
{
printf(" argv[%d] : ‘%s’ \n", i, argv[i]);
}
sprintf(JSON_HEADER,"%s", argv[1]);
fd = open(SERIAL_PORT, O_RDONLY | O_NOCTTY | O_SYNC);
if (fd < 0)
{
printf("Error opening %s: %s\n", SERIAL_PORT, strerror(errno));
return -1;
}
/* Get current time */
gettimeofday(&tv1, &tz1);
gettimeofday(&tv2, &tz2);
/* Open serial port */
set_interface_attribs(fd, BAUD_RATE);
/* Receive characters */
do
{
unsigned char buf[BUFFER_SIZE];
int rdlen;
int first_line = 1;
rdlen = read(fd, buf, sizeof(buf) - 1);
if (rdlen > 0)
{
int i = 0;
while (i < rdlen)
{
// Discard all special characters
const char c = buf[i];
if (((c >= 0x00) && (c <= 0x01)) || ((c >= 0x04) && (c <= 0x08)))
{
//printf("DEBUG --> Char 0x%x discarded in line: \"%s\"\n", c, line);
i++;
continue;
}
// Get character
line[pos] = c;
// If line ending is found
if (((c >= 0x02) && (c <= 0x03)) || ((c >= 0x0a) && (c <= 0x0f)))
{
// Close string
line[pos] = 0;
linelen = pos;
pos = 0;
// Discard first line as it may be truncated
if (first_line)
{
first_line = 0;
}
// Discard lines too small
else if (linelen < MIN_LINE_SIZE)
{
// Nothing to do
//printf("WARNING --> Line discarded because too small: \"%s\"\n", line);
}
// Discard incoherent lines
else if (line[linelen-2] != DEMILITER)
{
//printf("ERROR --> Ending delimiter not found on line: \"%s\"\n", line);
}
else
{
#ifdef DISPLAY_LINE_STRING
//printf("Read %d: \"%s\"\n", linelen, line);
#endif
#ifdef DISPLAY_LINE_HEX
unsigned char *p;
//printf("Read %d:", linelen);
for (p = line; linelen-- > 0; p++)
//printf(" 0x%x", *p);
//printf("\n");
#endif
// Verify checksum
if (isCheckSumOk(line) == 0)
{
//printf("SUCCESS --> Checksum OK on line: \"%s\"\n", line);
processLine(line);
}
}
}
else if (pos == sizeof(line) - 1)
{
// Close string
line[pos] = 0;
linelen = pos;
pos = 0;
printf("ERROR: no new line read in line: \"%s\"\n", line);
}
else if (pos == sizeof(buf) - 1)
{
// Close string
line[pos] = 0;
linelen = pos;
pos = 0;
printf("ERROR: no new line read in buffer: \"%s\"\n", buf);
}
else
{
pos++;
}
i++;
}
#ifdef DISPLAY_BUFFER_STRING
buf[rdlen] = 0;
printf("Read %d: \"%s\"\n", rdlen, buf);
#endif
#ifdef DISPLAY_BUFFER_HEX
unsigned char *p;
printf("Read %d:", rdlen);
for (p = buf; rdlen-- > 0; p++)
printf(" 0x%x", *p);
printf("\n");
#endif
}
else if (rdlen < 0)
{
printf("Error from read: %d: %s\n", rdlen, strerror(errno));
}
/* Check if it's time to send a message to Domoticz */
if (send_message)
{
send_message = 0;
//Calculate values to send
int SINST = (int)(teleinfo.SINSTS) - (int)(teleinfo.SINSTI);
//int SINST = (int)(teleinfo.SINSTI);
char SINST_str[12]; sprintf(SINST_str, "%d", SINST);
//int EAT = (int)(teleinfo.EAST) - (int)(teleinfo.EAIT);
int EAT = (int)(teleinfo.EAIT);
char EAT_str[12]; sprintf(EAT_str, "%d", EAT);
int EASF01 = (int)(teleinfo.EASF01);
char EASF01_str[12]; sprintf(EASF01_str, "%d", EASF01);
int EASF02 = (int)(teleinfo.EASF02);
char EASF02_str[12]; sprintf(EASF02_str, "%d", EASF02);
int IRMS1 = (int)(teleinfo.IRMS1);
char IRMS1_str[12]; sprintf(IRMS1_str, "%d", IRMS1);
int IRMS2 = (int)(teleinfo.IRMS2);
char IRMS2_str[12]; sprintf(IRMS2_str, "%d", IRMS2);
int IRMS3 = (int)(teleinfo.IRMS3);
char IRMS3_str[12]; sprintf(IRMS3_str, "%d", IRMS3);
int TARIF = (int)(teleinfo.TARIF);
char TARIF_str[12]; sprintf(TARIF_str, "%d", TARIF);
//Construction of messages to send
//On commence par le smartmeter
char message [1000];
strcpy(message, JSON_HEADER);
strcat(message, "?type=command¶m=udevice&idx=");
strcat(message, argv[2]);
strcat(message, "&nvalue=0&svalue=");
strcat(message, EASF02_str);
strcat(message, ";");
strcat(message, EASF01_str);
strcat(message, ";0;0;");
strcat(message, SINST_str);
strcat(message, ";0");
//Send message
if(sendUrl(message) == 0)
{
printf("DEBUG --> New message sent: \"%s\"\n", message);
}
//Puis le CM113, courant triphasé
strcpy(message, JSON_HEADER);
strcat(message, "?type=command¶m=udevice&idx=");
strcat(message, argv[3]);
strcat(message, "&nvalue=0&svalue=");
strcat(message, IRMS1_str);
strcat(message, ";");
strcat(message, IRMS2_str);
strcat(message, ";");
strcat(message, IRMS3_str);
strcat(message, ";");
//Send message
if(sendUrl(message) == 0)
{
printf("DEBUG --> New message sent: \"%s\"\n", message);
}
//Puis le tarif en cours 1= HC 2= HP
if (teleinfo.TARIF == 1)
{
sprintf(message, "%s?type=command¶m=udevice&idx=%s&nvalue=1&svalue=(1)+Heures+Creuses",
JSON_HEADER, argv[4]);
}
if (teleinfo.TARIF == 2)
{
sprintf(message, "%s?type=command¶m=udevice&idx=%s&nvalue=1&svalue=(2)+Heures+Pleines",
JSON_HEADER, argv[4]);
}
//Send message
if(sendUrl(message) == 0)
{
printf("DEBUG --> New message sent: \"%s\"\n", message);
}
exit(0);
}
else
{
gettimeofday(&tv2, &tz2);
if((tv2.tv_sec - tv1.tv_sec) >= 10)
{
send_message = 1;
tv1.tv_sec = tv2.tv_sec;
}
}
/* sleep and repeat read */
//sleep(1);
} while (1);
}