1 //******************************************************************
3 // Copyright 2014 Intel Corporation.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
11 // http://www.apache.org/licenses/LICENSE-2.0
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
26 #include "WrapResource.h"
27 #include "LineInput.h"
29 #define NEED_CLIENT { if (!m_client) return LR_NoClient; }
31 LineInput::LineInput(MiddleClient *client)
32 : m_client(client), m_server(nullptr),
33 m_obsCB(nullptr), m_observer(nullptr)
35 m_obsCB = std::bind(&LineInput::obsCB, this,
43 void LineInput::setServer(MiddleServer *server) {
55 const ssize_t n = getline(&line, &len, stdin);
59 m_observer->cancelObserve();
62 if (line[n - 1] == '\n') {
68 LineResult lr = processLine(line, result, m_obsCB);
77 LineResult LineInput::processLine(string command, stringstream& result, observecb_t cb)
81 if (parseLine(command, elems) != LR_OK) {
82 cerr << "syntax error" << endl;
88 if (elems[0] == "quit" || elems[0] == "exit")
91 if (elems.size() == 1) {
92 if (elems[0] == "help") {
93 return processHelp(elems, result);
94 } else if (elems[0] == "find") {
95 NEED_CLIENT return processFind(elems, result);
96 } else if (elems[0] == "show") {
97 NEED_CLIENT return processShow(elems, result);
99 } else if (elems.size() == 2) {
100 if (elems[0] == "details") {
101 NEED_CLIENT return processDetails(elems, result);
102 } else if (elems[0] == "get") {
103 NEED_CLIENT return processGet(elems, result);
104 } else if (elems[0] == "observe") {
105 NEED_CLIENT return processObserve(elems, result, cb);
106 } else if (elems[0] == "cancel") {
107 NEED_CLIENT return processCancel(elems, result);
110 if (elems[0] == "put") {
111 NEED_CLIENT return processPut(elems, result);
115 return processUnrecognized(elems, result);
118 LineResult LineInput::processHelp(elements_t& elems, stringstream& ss)
121 "\tfind\t\tFind resources\n"
122 "\tshow\t\tShow resources\n"
123 "\tdetails n\tShow details of resource n\n"
124 "\tget n\t\tGet value(s) of resource n\n"
125 "\tput n v\t\tPut value(s) to resource n\n"
126 "\tobserve n\tObserve value(s) of resource n\n"
127 "\thelp\t\tThis usage message\n"
128 "\nResource can be identified by Resource ID or Show index\n"
129 "\nValue in 'put' can be key=value or key:value\n\n"
134 LineResult LineInput::processUnrecognized(elements_t& elems, stringstream& ss)
136 ss << "Command not recognized\n";
137 processHelp(elems, ss);
138 return LR_Unrecognized;
141 LineResult LineInput::processFind(elements_t& elems, stringstream& ss)
143 m_client->findResources();
147 void LineInput::registerResourceWithServer(std::string & url) {
149 std::size_t index = url.rfind("/");
150 if (index != std::string::npos) {
151 type = url.substr(index+1);
153 const std::string resType = type;
154 const std::string iface = "MB_INTERFACE";
155 m_server->registerResource(url, resType, iface);
158 LineResult LineInput::processShow(elements_t& elems, stringstream& ss)
161 m_resourceList.clear();
162 resourcemap_t& pmap = m_client->m_resourceMap;
164 for (resourcemap_t::iterator it = pmap.begin(); it != pmap.end(); it++) {
165 string resID = it->first;
166 ss << index++ << '\t' << resID << '\n';
167 m_resourceList.push_back(resID);
169 registerResourceWithServer(resID);
176 LineResult LineInput::processDetails(elements_t& elems, stringstream& ss)
178 WrapResource *wres = resolveResource(elems[1], ss);
180 return LR_NoResource;
182 ss << wres->getResourceID() + " [ ";
183 for (auto &types : wres->getResourceTypes()) {
187 for (auto &ifs : wres->getResourceInterfaces()) {
194 void printJSONAsTable(std::string &jsonString) {
195 std::string str = jsonString;
196 std::string key, value;
197 size_t found = str.find("rep");
198 if (found == std::string::npos) { // not found
201 str = str.substr(found+5);
203 found = str.find(":");
204 if (found == std::string::npos) {
207 key = str.substr(1, found-1);
208 str = str.substr(found);
209 found = str.find(",");
210 if (found != std::string::npos) {
211 value = str.substr(1, found-1);
212 str = str.substr(found);
214 found = str.find("}");
215 if (found != std::string::npos) {
216 value = str.substr(1, found-1);
217 str = str.substr(found);
220 cout << key << "\t:" << value << endl;
224 LineResult LineInput::processGet(elements_t& elems, stringstream& ss)
226 WrapResource *wres = resolveResource(elems[1], ss);
228 return LR_NoResource;
230 token_t token = wres->getResource();
232 WrapRequest *wreq = wres->waitResource(token);
234 ss << "Get timed out\n";
238 std::string jsonRep = wreq->m_rep.getJSONRepresentation();
239 //ss << jsonRep << endl;
240 printJSONAsTable(jsonRep);
244 LineResult LineInput::processPut(elements_t& elems, stringstream& ss)
246 WrapResource *wres = resolveResource(elems[1], ss);
248 return LR_NoResource;
251 OCRepresentation rep;
254 for (size_t i = 2; i < elems.size(); i++) {
255 string elem = elems[i];
256 char *s = (char *)elem.c_str(); // elem string is intentionally damaged
257 char *key = strtok(s, "=:");
258 char *value = strtok(nullptr, "");
260 ss << "missing separator in element starting with " << key << '\n';
264 char delim = value[0];
265 size_t len = strlen(value);
266 if (delim == '\'' || delim == '"') {
267 if (len > 1 && delim == value[len - 1]) {
268 value[len - 1] = '\0';
272 string v(value, len);
273 stringmap_t formats = wres->getFormats();
275 format = formats.at(key);
277 cerr << "element in arg " << i << " has no format\n";
280 if (format == "bool") {
281 bool b = v != "0" && v != "false";
282 rep.setValue(key, b);
283 } else if (format == "number") {
285 int n = (int)strtol(value, &end, 10);
286 if (size_t(end - value) != len) {
287 double d = atof(value);
288 rep.setValue(key, d);
290 rep.setValue(key, n);
292 } else { // assume string
293 rep.setValue(key, v);
299 token_t token = wres->putResource(rep);
301 WrapRequest *wreq = wres->waitResource(token);
303 ss << "Get timed out\n";
310 LineResult LineInput::processObserve(elements_t& elems, stringstream& ss, observecb_t cb)
312 WrapResource *wres = resolveResource(elems[1], ss);
314 return LR_NoResource;
316 wres->observeResource(cb);
320 LineResult LineInput::processCancel(elements_t& elems, stringstream& ss)
322 WrapResource *wres = resolveResource(elems[1], ss);
324 return LR_NoResource;
326 wres->cancelObserve();
327 m_observer = nullptr;
331 WrapResource *LineInput::resolveResource(string resID, stringstream& ss)
334 string useID = resID;
335 int index = std::stoi(useID, &len);
337 if (len == resID.size()) { // it's an index, not a uri
338 if (size_t(index) >= m_resourceList.size()) {
339 cout << "Resource index out of range (use 'show')\n";
342 useID = m_resourceList[index]; // now it's a uri
345 resourcemap_t::iterator it = m_client->m_resourceMap.find(useID);
346 if (it == m_client->m_resourceMap.end()) {
347 cout << resID << " is currently not available\n";
354 void LineInput::obsCB(token_t token, const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode, const int sequenceNumber)
358 cout << "cb " << eCode << " " << sequenceNumber << '\n';
359 cout << rep.getJSONRepresentation() << "\n";
362 ParseState LineInput::finishElem(char*& e, elements_t& elems)
365 elems.push_back(m_elem);
370 ParseState LineInput::putCharInElem(char c, char *& e, ParseState newState)
373 if (size_t(e - m_elem) >= sizeof (m_elem))
374 throw 20; // hightly unlikely exception
379 * See processHelp() above for line format
381 LineResult LineInput::parseLine(string lineIn, elements_t& elems)
384 char c, *e, delim = 0;
386 size_t len = lineIn.size();
387 ParseState state = PS_Between;
388 const char *line = lineIn.c_str();
393 if (size_t(d - line) >= len) {
395 if (state == PS_Infirst || state == PS_Endsecond || (state == PS_Insecond && !delim)) {
396 state = finishElem(e, elems);
405 isSep1 = c == ' ' || c == '\t';
406 isSep2 = c == '=' || c == ':';
414 state = putCharInElem(c, e, PS_Infirst);
418 state = finishElem(e, elems);
423 state = PS_Startsecond;
425 putCharInElem(c, e, state);
428 if (isSep1 || isSep2)
430 if (c == '\'' || c == '"' || c == '|')
432 state = putCharInElem(c, e, PS_Insecond);
435 if (isSep1 && delim == 0) {
436 state = finishElem(e, elems);
440 state = PS_Endsecond;
446 state = finishElem(e, elems);