|
@@ -0,0 +1,144 @@
|
|
|
+/*
|
|
|
+ * openhab.cpp
|
|
|
+ *
|
|
|
+ * Created on: May 25, 2019
|
|
|
+ * Author: Philipp Hinz
|
|
|
+ */
|
|
|
+
|
|
|
+#include <stdlib.h>
|
|
|
+#include <pthread.h>
|
|
|
+#include <stdio.h> /* printf, sprintf */
|
|
|
+#include <unistd.h> /* read, write, close */
|
|
|
+#include <string.h> /* memcpy, memset */
|
|
|
+#include <sys/socket.h> /* socket, connect */
|
|
|
+#include <netinet/in.h> /* struct sockaddr_in, struct sockaddr */
|
|
|
+#include <netdb.h> /* 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);
|
|
|
+ logger(V_BASIC, "Initialized OpenHAB state updater with target %s:%d\n",
|
|
|
+ OPENHAB_IP, OPENHAB_PORT);
|
|
|
+}
|
|
|
+
|