/* * Copyright (C) 2015-2018 "IoT.bzh" * Author Gabin Fodop * Author José Bollo * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #define _GNU_SOURCE #include #include #include #include #include #include #include extern "C" { #include "json-c/json.h" #include "afb-wsj1.h" #include "afb-ws-client.h" } #include #include #include #include #include #include namespace afb { class wsj1 { public: wsj1() noexcept = default; wsj1(const wsj1 &other) = delete; wsj1(wsj1 &&other) noexcept { wsj1_ = other.wsj1_; other.wsj1_ = nullptr; } wsj1(const std::string &uri) { connect(uri); } wsj1(const char *uri) { connect(uri); } ~wsj1() { if (wsj1_) disconnect(); } void connect(const std::string &uri) { connect(uri.c_str()); } void connect(const char *uri); void disconnect(); void call(const char *api, const char *verb, char *request, std::function onreply); #if 0 void call(const char *api, const char *verb, json_object *request, std::function &onreply) { call(api,verb,json_object_to_json_string_ext(request,JSON_C_TO_STRING_PLAIN),[](const char *x){onreply(std::string(x));}); }; void call(const std::string &api, const std::string &verb, const std::string &request, std::function &onreply) { call(api.c_str(), verb.c_str(), request.c_str(), [=](const char *x){onreply(std::string(x));}); } #endif public: class msg { friend class wsj1; msg(afb_wsj1_msg *msg) : msg_{msg} {} afb_wsj1_msg *msg_; public: }; private: afb_wsj1 *wsj1_ = nullptr; private: static struct afb_wsj1_itf wsj1_itf; static void itf_hangup_(void *closure, struct afb_wsj1 *wsj1){}; static void itf_on_call_(void *closure, const char *api, const char *verb, struct afb_wsj1_msg *msg){}; static void itf_on_event_(void *closure, const char *event, struct afb_wsj1_msg *msg); private: void on_hangup_(struct afb_wsj1 *wsj1); void on_call_(const char *api, const char *verb, struct afb_wsj1_msg *msg); void on_event_(const char *event, struct afb_wsj1_msg *msg); private: static sd_event *eloop_(); private: static void on_reply_(void *closure, struct afb_wsj1_msg *msg); }; struct afb_wsj1_itf wsj1::wsj1_itf = { wsj1::itf_hangup_, wsj1::itf_on_call_, wsj1::itf_on_event_ }; void wsj1::connect(const char *uri) { if (wsj1_) throw std::runtime_error("already-connected"); wsj1_ = afb_ws_client_connect_wsj1(eloop_(), uri, &wsj1_itf, reinterpret_cast(this)); if (!wsj1_) throw std::runtime_error("connection-failed"); } void wsj1::disconnect() { if (!wsj1_) throw std::runtime_error("not-connected"); afb_wsj1_unref(wsj1_); wsj1_ = nullptr; } void wsj1::itf_on_event_(void *closure, const char *event, struct afb_wsj1_msg *msg) { reinterpret_cast(closure)->on_event_(event, msg); } void wsj1::on_event_(const char *event, struct afb_wsj1_msg *msg) { } void wsj1::call(const char *api, const char *verb, char *request, std::function onreply) { if (!wsj1_) throw std::runtime_error("not-connected"); std::function *onrep = new std::function(onreply); afb_wsj1_call_s(wsj1_,api,verb,request,on_reply_,reinterpret_cast(onrep)); } void wsj1::on_reply_(void *closure, struct afb_wsj1_msg *msg) { std::function *onreply = reinterpret_cast*>(closure); (*onreply)(afb_wsj1_msg_object_s(msg)); afb_wsj1_msg_unref(msg); delete onreply; } sd_event *wsj1::eloop_() { static sd_event *el = nullptr; static std::mutex lock; std::lock_guard guard(lock); if (!el) { if (sd_event_new(&el) == 0) { std::thread t(sd_event_loop, el); t.detach(); } } return el; } void wsj1::on_hangup_(struct afb_wsj1 *wsj1) { }; void wsj1::on_call_(const char *api, const char *verb, struct afb_wsj1_msg *msg) { }; } // faire un test qui verifi le fonctionnement de la classe, // il faut faire bien attention avec la fonction call qui doit se terminer avan tle programme, un get char ou un cin // ecrire lma fonction on reply qui affichhe le resultat de la requete à l'ecran