Skip to content

Commit

Permalink
- Implemented binary-packed I/O over WebSocket
Browse files Browse the repository at this point in the history
- API command can now be sent also via websocket (either binary-packed or clear text)
- WebSocket server default port is now 8188 (same as HG server)
  • Loading branch information
genemars committed Jan 11, 2024
1 parent 187fe36 commit 30e69b2
Show file tree
Hide file tree
Showing 19 changed files with 238 additions and 120 deletions.
2 changes: 1 addition & 1 deletion examples/rf-transceiver/api/RCSwitchHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ namespace Service { namespace API {



bool RCSwitchHandler::handleRequest(APIRequest *command, WebServer &server) {
bool RCSwitchHandler::handleRequest(APIRequest *command, ResponseCallback* responseCallback) {
if (command->Domain == (IOEventDomains::HomeAutomation_RCS)
&& command->Address == CONFIG_RCSwitchRF_MODULE_ADDRESS
&& command->Command == "Control.SendRaw") {
Expand Down
2 changes: 1 addition & 1 deletion examples/rf-transceiver/api/RCSwitchHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ namespace Service { namespace API {
RCSwitchHandler(IO::RCS::RFTransmitter* transmitter);
void init() override;
bool canHandleDomain(String* domain) override;
bool handleRequest(APIRequest *request, WebServer &server) override;
bool handleRequest(APIRequest *request, ResponseCallback* responseCallback) override;
bool handleEvent(IIOEventSender *sender,
const char* domain, const char* address,
const unsigned char *eventPath, void *eventData, IOEventDataType dataType) override;
Expand Down
4 changes: 2 additions & 2 deletions examples/shutter/api/ShutterHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ namespace Service { namespace API {
}


bool ShutterHandler::handleRequest(APIRequest *command, WebServer &server) {
bool ShutterHandler::handleRequest(APIRequest *command, ResponseCallback* responseCallback) {

if (command->Domain == (IOEventDomains::Automation_Components)
&& command->Address == SERVO_MODULE_ADDRESS) {
Expand All @@ -64,7 +64,7 @@ namespace Service { namespace API {

servoControl->setLevel(level);

command->Response = R"({ "ResponseText": "OK" })";
responseCallback->writeAll(R"({ "ResponseText": "OK" })");

} else if (command->Command == "Control.Close" || command->Command == "Control.Off") {

Expand Down
2 changes: 1 addition & 1 deletion examples/shutter/api/ShutterHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ namespace Service { namespace API {
ShutterHandler(ShutterControl* servoControl);
void init() override;
bool canHandleDomain(String* domain) override;
bool handleRequest(APIRequest *request, WebServer &server) override;
bool handleRequest(APIRequest *request, ResponseCallback* responseCallback) override;
bool handleEvent(IIOEventSender *sender,
const char* domain, const char* address,
const unsigned char *eventPath, void *eventData, IOEventDataType dataType) override;
Expand Down
2 changes: 1 addition & 1 deletion examples/x10-transceiver/api/X10Handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ namespace Service { namespace API {
}


bool X10Handler::handleRequest(APIRequest *command, WebServer &server) {
bool X10Handler::handleRequest(APIRequest *command, ResponseCallback* responseCallback) {

if (command->Domain == (IOEventDomains::HomeAutomation_X10)
&& command->Address == CONFIG_X10RF_MODULE_ADDRESS
Expand Down
2 changes: 1 addition & 1 deletion examples/x10-transceiver/api/X10Handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ namespace Service { namespace API {
X10Handler(IO::X10::RFTransmitter* transmitter);
void init() override;
bool canHandleDomain(String* domain) override;
bool handleRequest(APIRequest *request, WebServer &server) override;
bool handleRequest(APIRequest *request, ResponseCallback* responseCallback) override;
bool handleEvent(IIOEventSender *sender,
const char* domain, const char* address,
const unsigned char *eventPath, void *eventData, IOEventDataType dataType) override;
Expand Down
3 changes: 3 additions & 0 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,20 @@
[platformio]
src_dir = .
include_dir = ./src
data_dir = ./data/web

[env]
build_src_filter = -<*> +<src/*>
framework = arduino
board = esp32dev
board_build.filesystem = littlefs
lib_deps =
[email protected]
thijse/[email protected]
[email protected]
[email protected]
vortigont/[email protected]
hideakitai/MsgPack
adafruit/[email protected]
[email protected]
mbed-seeed/[email protected]+sha.f56002898ee8
Expand Down
67 changes: 30 additions & 37 deletions src/HomeGenie.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,12 @@ namespace Service {

void HomeGenie::begin() {
netManager.begin();
netManager.getHttpServer().addHandler(this);
netManager.setRequestHandler(this);
#ifndef DISABLE_BLE
netManager.getBLEManager().addHandler(this);
#endif
ioManager.begin();
ioManager.setOnEventCallback(this);
ioManager.setEventReceiver(this);

// Initialize custom API handlers
for (int i = 0; i < handlers.size(); i++) {
Expand Down Expand Up @@ -117,7 +117,8 @@ namespace Service {
}


// BEGIN IIOEventSender interface methods
// BEGIN IIOEventReceiver interface methods

void HomeGenie::onIOEvent(IIOEventSender *sender, const char* domain, const char* address, const unsigned char *eventPath, void *eventData,
IOEventDataType dataType) {
String event = String((char *) eventPath);
Expand All @@ -132,36 +133,31 @@ namespace Service {
}
}
}
// END IIOEventSender

// BEGIN RequestHandler interface methods
bool HomeGenie::canHandle(HTTPMethod method, String uri) {
return uri != nullptr && uri.startsWith("/api/");
}
// END IIOEventReceiver

bool HomeGenie::handle(WebServer &server, HTTPMethod requestMethod, String requestUri) {
auto command = APIRequest::parse(requestUri);
if (api(&command, server)) {
if (command.Response.length() > 0) {
server.send(200, "application/json", command.Response);
}
} else {
server.send(400, "application/json", command.Response);
}
return true;

// BEGIN NetRequestHandler interface methods

bool HomeGenie::onNetRequest(void *sender, const char* requestMessage, ResponseCallback* responseCallback) {
auto command = APIRequest::parse(requestMessage);
return api(&command, responseCallback);
}
// END RequestHandler interface methods

bool HomeGenie::api(APIRequest *request, WebServer &server) {
// END NetRequestHandler


bool HomeGenie::api(APIRequest *request, ResponseCallback* responseCallback) {
for (int i = 0; i < handlers.size(); i++) {
auto handler = handlers.get(i);
if (handler->canHandleDomain(&request->Domain)) {
return handler->handleRequest(request, server);
return handler->handleRequest(request, responseCallback);
}
}
return false;
}


Module* HomeGenie::getDefaultModule() {
auto domain = String(IOEventDomains::HomeAutomation_HomeGenie);
auto address = String(CONFIG_BUILTIN_MODULE_ADDRESS);
Expand Down Expand Up @@ -193,21 +189,19 @@ namespace Service {
return out.c_str();
}

unsigned int HomeGenie::writeModuleJSON(WebServer *server, String* domain, String* address) {
auto outputCallback = APIHandlerOutputCallback(server);
unsigned int HomeGenie::writeModuleJSON(ResponseCallback *responseCallback, String* domain, String* address) {
auto module = getModule(domain, address);
if (module != nullptr) {
String out = getModuleJSON(module);
outputCallback.write(out);
responseCallback->write(out.c_str());
}
return outputCallback.outputLength;
return responseCallback->contentLength;
}

unsigned int HomeGenie::writeModuleListJSON(WebServer *server) {
unsigned int HomeGenie::writeModuleListJSON(ResponseCallback *responseCallback) {
bool firstModule = true;
auto outputCallback = APIHandlerOutputCallback(server);
String out = "[";
outputCallback.write(out);
responseCallback->write(out.c_str());
for (int i = 0; i < handlers.size(); i++) {
auto handler = handlers.get(i);
auto moduleList = handler->getModuleList();
Expand All @@ -221,17 +215,16 @@ namespace Service {
out = "";
}
out += getModuleJSON(module);
outputCallback.write(out);
responseCallback->write(out.c_str());
}
}
out = "]\n";
outputCallback.write(out);
return outputCallback.outputLength;
responseCallback->write(out.c_str());
return responseCallback->contentLength;
}

unsigned int HomeGenie::writeGroupListJSON(WebServer *server) {
unsigned int HomeGenie::writeGroupListJSON(ResponseCallback *responseCallback) {
bool firstModule = true;
auto outputCallback = APIHandlerOutputCallback(server);
String defaultGroupName = "Dashboard";
#ifndef CONFIGURE_WITH_WPA
Preferences preferences;
Expand All @@ -243,7 +236,7 @@ namespace Service {
}
#endif
String out = R"([{"Name": ")" + defaultGroupName + R"(", "Modules": [)";
outputCallback.write(out);
responseCallback->write(out.c_str());
for (int i = 0; i < handlers.size(); i++) {
auto handler = handlers.get(i);
auto moduleList = handler->getModuleList();
Expand All @@ -257,13 +250,13 @@ namespace Service {
}
auto module = moduleList->get(m);
out += R"({"Address": ")" + module->address + R"(", "Domain": ")" + module->domain + R"("})";
outputCallback.write(out);
responseCallback->write(out.c_str());
}

}
out = "]}]\n";
outputCallback.write(out);
return outputCallback.outputLength;
responseCallback->write(out.c_str());
return responseCallback->contentLength;
}


Expand Down
28 changes: 16 additions & 12 deletions src/HomeGenie.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ namespace Service {
using namespace Net;
using namespace Service::API;

class HomeGenie: RequestHandler, IIOEventReceiver {
class HomeGenie: IIOEventReceiver, NetRequestHandler {
public:
static HomeGenie* getInstance() {
if (serviceInstance == nullptr) {
Expand All @@ -72,10 +72,8 @@ namespace Service {
// IIOEventReceiver overrides
void onIOEvent(IIOEventSender *sender, const char* domain, const char* address, const unsigned char *eventPath, void *eventData, IOEventDataType dataType) override;

// RequestHandler overrides
bool canHandle(HTTPMethod method, String uri) override;
bool handle(WebServer& server, HTTPMethod requestMethod, String requestUri) override;
bool api(APIRequest *request, WebServer &server);
// NetRequestHandler overrides
bool onNetRequest(void* sender, const char* requestMessage, ResponseCallback* responseCallback) override;

/**
*
Expand All @@ -90,21 +88,27 @@ namespace Service {
*/
bool addIOHandler(IIOEventSender* handler);

NetManager& getNetManager();
IOManager& getIOManager();
EventRouter& getEventRouter();

/**
*
* @param request
* @param responseCallback
* @return
*/
bool api(APIRequest *request, ResponseCallback* responseCallback);


NetManager& getNetManager();
IOManager& getIOManager();
EventRouter& getEventRouter();


Module* getDefaultModule();
Module* getModule(String* domain, String* address);

const char* getModuleJSON(Module* module);
unsigned int writeModuleListJSON(WebServer *server);
unsigned int writeModuleJSON(WebServer *server, String* domain, String* address);
unsigned int writeGroupListJSON(WebServer *server);
unsigned int writeModuleListJSON(ResponseCallback *outputCallback);
unsigned int writeModuleJSON(ResponseCallback *outputCallback, String* domain, String* address);
unsigned int writeGroupListJSON(ResponseCallback *outputCallback);

static String createModule(const char *domain, const char *address, const char *name, const char* description, const char *deviceType, const char *parameters);
static String createModuleParameter(const char *name, const char* value, const char *timestamp);
Expand Down
6 changes: 3 additions & 3 deletions src/io/IOManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,13 @@ namespace IO {
return true;
}

void IOManager::setOnEventCallback(IIOEventReceiver *callback) {
ioEventCallback = callback;
void IOManager::setEventReceiver(IIOEventReceiver *receiver) {
ioEventReceiver = receiver;
}

void IOManager::onIOEvent(IIOEventSender *sender, const char* domain, const char* address, const unsigned char *eventPath, void *eventData, IOEventDataType dataType) {
// route event to HomeGenie
ioEventCallback->onIOEvent(sender, domain, address, eventPath, eventData, dataType);
ioEventReceiver->onIOEvent(sender, domain, address, eventPath, eventData, dataType);
}

}
6 changes: 3 additions & 3 deletions src/io/IOManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,17 @@ namespace IO {

void begin();

bool addEventSender(IIOEventSender* sender);
bool addEventSender(IIOEventSender *);

// IIOEventReceiver interface
void onIOEvent(IIOEventSender *, const char*, const char*, const uint8_t *, void *, IOEventDataType);

void setOnEventCallback(IIOEventReceiver *);
void setEventReceiver(IIOEventReceiver *);

private:
// Diagnostics
System::Diagnostics *systemDiagnostics;
IIOEventReceiver *ioEventCallback;
IIOEventReceiver *ioEventReceiver;
LinkedList<IIOEventSender*> eventSenders;
};

Expand Down
Loading

0 comments on commit 30e69b2

Please sign in to comment.