SinricPro Library
SinricProWebsocket.h
1 /*
2  * Copyright (c) 2019 Sinric. All rights reserved.
3  * Licensed under Creative Commons Attribution-Share Alike (CC BY-SA)
4  *
5  * This file is part of the Sinric Pro (https://github.com/sinricpro/)
6  */
7 
8 
9 #ifndef _SINRICPRO_WEBSOCKET_H__
10 #define _SINRICPRO_WEBSOCKET_H__
11 
12 #if defined ESP8266
13  #include <ESP8266WiFi.h>
14 #endif
15 #if defined ESP32
16  #include <WiFi.h>
17 #endif
18 
19 #include <WebSocketsClient.h>
20 #include <ArduinoJson.h>
21 #include "SinricProDebug.h"
22 #include "SinricProConfig.h"
23 #include "SinricProQueue.h"
24 #include "SinricProInterface.h"
25 
26 class websocketListener
27 {
28  public:
29  typedef std::function<void(void)> wsConnectedCallback;
30  typedef std::function<void(void)> wsDisconnectedCallback;
31 
32  websocketListener();
33  ~websocketListener();
34 
35  void begin(String server, String socketAuthToken, String deviceIds, SinricProQueue_t* receiveQueue);
36  void handle();
37  void stop();
38  bool isConnected() { return _isConnected; }
39  void setRestoreDeviceStates(bool flag) { this->restoreDeviceStates = flag; };
40 
41  void sendMessage(String &message);
42 
43  void onConnected(wsConnectedCallback callback) { _wsConnectedCb = callback; }
44  void onDisconnected(wsDisconnectedCallback callback) { _wsDisconnectedCb = callback; }
45 
46  void disconnect() { webSocket.disconnect(); }
47  private:
48  bool _begin = false;
49  bool _isConnected = false;
50  bool restoreDeviceStates = false;
51 
52  WebSocketsClient webSocket;
53 
54  wsConnectedCallback _wsConnectedCb;
55  wsDisconnectedCallback _wsDisconnectedCb;
56 
57  void webSocketEvent(WStype_t type, uint8_t * payload, size_t length);
58  void setExtraHeaders();
59  SinricProQueue_t* receiveQueue;
60  String deviceIds;
61  String socketAuthToken;
62 };
63 
64 void websocketListener::setExtraHeaders() {
65  String headers = "appkey:" + socketAuthToken + "\r\n";
66  headers += "deviceids:" + deviceIds + "\r\n";
67  headers += "restoredevicestates:" + String(restoreDeviceStates?"true":"false") + "\r\n";
68  #ifdef ESP8266
69  headers += "platform:ESP8266\r\n";
70  #endif
71  #ifdef ESP32
72  headers += "platform:ESP32\r\n";
73  #endif
74  headers += "version:" + String(SINRICPRO_VERSION);
75  DEBUG_SINRIC("[SinricPro:Websocket]: headers: \r\n%s\r\n", headers.c_str());
76  webSocket.setExtraHeaders(headers.c_str());
77 }
78 
79 websocketListener::websocketListener() : _isConnected(false) {}
80 
81 websocketListener::~websocketListener() {
82  stop();
83 }
84 
85 void websocketListener::begin(String server, String socketAuthToken, String deviceIds, SinricProQueue_t* receiveQueue) {
86  if (_begin) return;
87  _begin = true;
88 
89  this->receiveQueue = receiveQueue;
90  this->socketAuthToken = socketAuthToken;
91  this->deviceIds = deviceIds;
92 
93  DEBUG_SINRIC("[SinricPro:Websocket]: Connecting to WebSocket Server (%s)\r\n", server.c_str());
94 
95  if (_isConnected) {
96  stop();
97  }
98  setExtraHeaders();
99  webSocket.onEvent([&](WStype_t type, uint8_t * payload, size_t length) { webSocketEvent(type, payload, length); });
100  webSocket.enableHeartbeat(WEBSOCKET_PING_INTERVAL, WEBSOCKET_PING_TIMEOUT, WEBSOCKET_RETRY_COUNT);
101  webSocket.begin(server, SINRICPRO_SERVER_PORT, "/"); // server address, port and URL
102 }
103 
104 void websocketListener::handle() {
105  webSocket.loop();
106 }
107 
108 void websocketListener::stop() {
109  if (_isConnected) {
110  webSocket.disconnect();
111  }
112  _begin = false;
113 }
114 
115 void websocketListener::sendMessage(String &message) {
116  webSocket.sendTXT(message);
117 }
118 
119 
120 void websocketListener::webSocketEvent(WStype_t type, uint8_t * payload, size_t length)
121 {
122  switch (type) {
123  case WStype_DISCONNECTED:
124  if (_isConnected) {
125  DEBUG_SINRIC("[SinricPro:Websocket]: disconnected\r\n");
126  if (_wsDisconnectedCb) _wsDisconnectedCb();
127  _isConnected = false;
128  }
129  break;
130  case WStype_CONNECTED:
131  _isConnected = true;
132  DEBUG_SINRIC("[SinricPro:Websocket]: connected\r\n");
133  if (_wsConnectedCb) _wsConnectedCb();
134  if (restoreDeviceStates) {
135  restoreDeviceStates=false;
136  setExtraHeaders();
137  }
138  break;
139  case WStype_TEXT: {
140  SinricProMessage* request = new SinricProMessage(IF_WEBSOCKET, (char*)payload);
141  DEBUG_SINRIC("[SinricPro:Websocket]: receiving data\r\n");
142  receiveQueue->push(request);
143  break;
144  }
145  default: break;
146  }
147 }
148 
149 #endif