/* * openhab.cpp * * Created on: May 25, 2019 * Author: Philipp Hinz */ #include #include #include /* printf, sprintf */ #include /* read, write, close */ #include /* memcpy, memset */ #include /* socket, connect */ #include /* struct sockaddr_in, struct sockaddr */ #include /* struct hostent, gethostbyname */ #include "openhab.h" #include "events.h" #include "timer.h" #include "logger.h" #include "coffee.h" coffee_status_t openhabCoffeeState = STATE_IDLE; // Don't use OFF to push initial state timer httpTimer(httpTimerHandler); #define NL "\r\n" // New line for HTTP Requests /** * Updates the display state to the matching coffee state * @param event Event data */ void openhabStateUpdated(event_t *event) { if (event->len != sizeof(coffee_status_t)) { logger_error("Invalid use of event %s\n", event->event); return; } coffee_status_t state = *(coffee_status_t*) event->data; if ((openhabCoffeeState == STATE_OFF && state != STATE_OFF) || // Machine turns on (state == STATE_OFF && openhabCoffeeState != STATE_OFF)) { // machine turns off openhabCoffeeState = state; httpTimer.call(); } } /** * This is the handler for time based stripe effects * @param *threadid Thread ID */ void *httpTimerHandler(void *threadid) { struct hostent *server; struct sockaddr_in serv_addr; int sockfd, bytes, sent, received, total; char message[1024], response[4096], value[4]; sprintf(value, "%s", (openhabCoffeeState == STATE_OFF ? "OFF" : "ON")); /* fill in the parameters */ sprintf(message, "PUT %s HTTP/1.1" NL "Host: %s" NL "Connection: close" NL "Content-Type: text/plain" NL "Content-Length: %d" NL NL "%s", OPENHAB_URI, OPENHAB_IP, strlen(value), value); /* create the socket */ sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { logger_error("%s:%d could not open socket\n", __FILE__, __LINE__); pthread_exit(NULL); } /* lookup the ip address */ server = gethostbyname(OPENHAB_IP); if (server == NULL) { logger_error("%s:%d no such host %s\n", __FILE__, __LINE__, OPENHAB_IP); pthread_exit(NULL); } /* fill in the structure */ memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(OPENHAB_PORT); memcpy(&serv_addr.sin_addr.s_addr, server->h_addr,server->h_length); /* connect the socket */ if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) { logger_error("%s:%d could not connect to %s on port %d\n", __FILE__, __LINE__, OPENHAB_IP, OPENHAB_PORT); pthread_exit(NULL); } /* send the request */ total = strlen(message); sent = 0; do { bytes = write(sockfd, message + sent, total - sent); if (bytes < 0) { logger_error("%s:%d ERROR writing message to socket\n", __FILE__, __LINE__); pthread_exit(NULL); } if (bytes == 0) break; sent += bytes; } while (sent < total); /* receive the response */ memset(response, 0, sizeof(response)); total = sizeof(response) - 1; received = 0; do { bytes = read(sockfd, response + received, total - received); if (bytes < 0) { logger_error("%s:%d ERROR reading response from socket\n", __FILE__, __LINE__); pthread_exit(NULL); } if (bytes == 0) break; received += bytes; } while (received < total); if (received == total) { logger_error("%s:%d ERROR storing complete response from socket\n", __FILE__, __LINE__); pthread_exit(NULL); } /* close the socket */ close(sockfd); /* process response */ logger(V_HAL, "HTTP Response:\n%s\n", response); pthread_exit(NULL); } void openhabInit(void) { event_subscribe("statechange", &openhabStateUpdated, "openhab.cpp"); logger(V_BASIC, "Initialized OpenHAB state updater with target %s:%d\n", OPENHAB_IP, OPENHAB_PORT); }