openhab.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. /*
  2. * openhab.cpp
  3. *
  4. * Created on: May 25, 2019
  5. * Author: Philipp Hinz
  6. */
  7. #include <stdlib.h>
  8. #include <pthread.h>
  9. #include <stdio.h> /* printf, sprintf */
  10. #include <unistd.h> /* read, write, close */
  11. #include <string.h> /* memcpy, memset */
  12. #include <sys/socket.h> /* socket, connect */
  13. #include <netinet/in.h> /* struct sockaddr_in, struct sockaddr */
  14. #include <netdb.h> /* struct hostent, gethostbyname */
  15. #include "openhab.h"
  16. #include "events.h"
  17. #include "timer.h"
  18. #include "logger.h"
  19. #include "coffee.h"
  20. coffee_status_t openhabCoffeeState = STATE_IDLE; // Don't use OFF to push initial state
  21. timer httpTimer(httpTimerHandler);
  22. #define NL "\r\n" // New line for HTTP Requests
  23. /**
  24. * Updates the display state to the matching coffee state
  25. * @param event Event data
  26. */
  27. void openhabStateUpdated(event_t *event) {
  28. if (event->len != sizeof(coffee_status_t)) {
  29. logger_error("Invalid use of event %s\n", event->event);
  30. return;
  31. }
  32. coffee_status_t state = *(coffee_status_t*) event->data;
  33. if ((openhabCoffeeState == STATE_OFF && state != STATE_OFF) || // Machine turns on
  34. (state == STATE_OFF && openhabCoffeeState != STATE_OFF)) { // machine turns off
  35. openhabCoffeeState = state;
  36. httpTimer.call();
  37. }
  38. }
  39. /**
  40. * This is the handler for time based stripe effects
  41. * @param *threadid Thread ID
  42. */
  43. void *httpTimerHandler(void *threadid) {
  44. struct hostent *server;
  45. struct sockaddr_in serv_addr;
  46. int sockfd, bytes, sent, received, total;
  47. char message[1024], response[4096], value[4];
  48. sprintf(value, "%s", (openhabCoffeeState == STATE_OFF ? "OFF" : "ON"));
  49. /* fill in the parameters */
  50. sprintf(message, "PUT %s HTTP/1.1" NL
  51. "Host: %s" NL
  52. "Connection: close" NL
  53. "Content-Type: text/plain" NL
  54. "Content-Length: %d" NL NL
  55. "%s", OPENHAB_URI, OPENHAB_IP, strlen(value), value);
  56. /* create the socket */
  57. sockfd = socket(AF_INET, SOCK_STREAM, 0);
  58. if (sockfd < 0) {
  59. logger_error("%s:%d could not open socket\n", __FILE__, __LINE__);
  60. pthread_exit(NULL);
  61. }
  62. /* lookup the ip address */
  63. server = gethostbyname(OPENHAB_IP);
  64. if (server == NULL) {
  65. logger_error("%s:%d no such host %s\n", __FILE__, __LINE__, OPENHAB_IP);
  66. pthread_exit(NULL);
  67. }
  68. /* fill in the structure */
  69. memset(&serv_addr, 0, sizeof(serv_addr));
  70. serv_addr.sin_family = AF_INET;
  71. serv_addr.sin_port = htons(OPENHAB_PORT);
  72. memcpy(&serv_addr.sin_addr.s_addr, server->h_addr,server->h_length);
  73. /* connect the socket */
  74. if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr))
  75. < 0) {
  76. logger_error("%s:%d could not connect to %s on port %d\n", __FILE__,
  77. __LINE__, OPENHAB_IP, OPENHAB_PORT);
  78. pthread_exit(NULL);
  79. }
  80. /* send the request */
  81. total = strlen(message);
  82. sent = 0;
  83. do {
  84. bytes = write(sockfd, message + sent, total - sent);
  85. if (bytes < 0) {
  86. logger_error("%s:%d ERROR writing message to socket\n", __FILE__,
  87. __LINE__);
  88. pthread_exit(NULL);
  89. }
  90. if (bytes == 0)
  91. break;
  92. sent += bytes;
  93. } while (sent < total);
  94. /* receive the response */
  95. memset(response, 0, sizeof(response));
  96. total = sizeof(response) - 1;
  97. received = 0;
  98. do {
  99. bytes = read(sockfd, response + received, total - received);
  100. if (bytes < 0) {
  101. logger_error("%s:%d ERROR reading response from socket\n", __FILE__,
  102. __LINE__);
  103. pthread_exit(NULL);
  104. }
  105. if (bytes == 0)
  106. break;
  107. received += bytes;
  108. } while (received < total);
  109. if (received == total) {
  110. logger_error("%s:%d ERROR storing complete response from socket\n",
  111. __FILE__, __LINE__);
  112. pthread_exit(NULL);
  113. }
  114. /* close the socket */
  115. close(sockfd);
  116. /* process response */
  117. logger(V_HAL, "HTTP Response:\n%s\n", response);
  118. pthread_exit(NULL);
  119. }
  120. void openhabInit(void) {
  121. event_subscribe("statechange", &openhabStateUpdated, "openhab.cpp");
  122. logger(V_BASIC, "Initialized OpenHAB state updater with target %s:%d\n",
  123. OPENHAB_IP, OPENHAB_PORT);
  124. }