AGirs
Girs.cpp
Go to the documentation of this file.
1 /*
2 Copyright (C) 2014,2015,2017 Bengt Martensson.
3 
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or (at
7 your option) any later version.
8 
9 This program is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License along with
15 this program. If not, see http://www.gnu.org/licenses/.
16 */
17 
18 #include "config.h"
19 #include "GirsLib/LedLcdManager.h"
20 #include "GirsLib/GirsUtils.h"
21 #ifdef ARDUINO
22 #include <avr/pgmspace.h>
23 #else
24 #define PROGMEM
25 #endif
26 
27 // Conditional includes
28 #if defined(ETHERNET) & !defined(ARDUINO)
29 #error not supported
30 #endif
31 
32 #ifdef ETHERNET
33 #include <Ethernet.h>
34 #include <IPAddress.h>
35 #endif // ETHERNET
36 
37 #ifdef LCD
38 #include <LiquidCrystal_I2C.h>
39 #endif
40 
41 #ifdef RECEIVE
42 #include <IrReceiverSampler.h>
43 #endif
44 
45 #ifdef TRANSMIT
46 #include <IrSenderPwm.h>
47 #endif
48 #if defined(RECEIVE)
49 #include <IrReceiverSampler.h>
50 #endif
51 
52 #ifdef CAPTURE
53 #include <IrWidgetAggregating.h>
54 #endif
55 
56 #ifdef NON_MOD
57 #include <IrSenderNonMod.h>
58 #endif
59 
60 #ifdef DECODER
61 #ifndef RECEIVE
62 #error DECODER without RECEIVE is nonsensical, aborting.
63 #endif
64 #include <MultiDecoder.h>
65 #endif
66 
67 #ifdef RENDERER
68 #ifndef TRANSMIT
69 #error RENDER without TRANSMIT is nonsensical, aborting.
70 #endif
71 #include <IrSignal.h>
72 #include <Nec1Renderer.h>
73 #include <Rc5Renderer.h>
74 #endif
75 
76 #ifdef NAMED_COMMANDS
77 #error NAMED_COMMANDS is presently not supported
78 #endif
79 
80 #ifdef BEACON
81 #include <Beacon.h>
82 #endif
83 
84 #ifdef PRONTO
85 #include <Pronto.h>
86 #endif
87 
88 #ifdef ARDUINO
89 #else
90 #include <string.h> // for strlen
91 #endif
92 
93 #if defined(CONFIGURABLE_LEDS) & (! defined(PARAMETERS) | !defined(LED))
94 #error CONFIGURABLE_LEDS defined but not PARAMETERS and LED, aborting.
95 #endif
96 
97 #ifdef CONFIGURABLE_LEDS
98 #define LED_PARAMETER_CONST
99 #else
100 #define LED_PARAMETER_CONST const
101 #endif
102 
103 #ifdef PARAMETERS
104 #define PARAMETERS_NAME Parameters
105 #define PARAMETER_CONST
106 #else
107 #define PARAMETERS_NAME
108 #define PARAMETER_CONST const
109 #endif
110 
111 #ifdef LED
112 #ifdef TRANSMITLED
114 #endif
115 
116 #ifdef RECEIVELED
118 #endif
119 
120 #ifdef CAPTURELED
122 #endif
123 
124 #ifdef COMMANDLED
126 #endif
127 #endif // LED
128 
129 #ifdef CAPTURE
131 static const unsigned sensorNo = 1; // presently, only one supported
132 #endif
133 #ifdef RECEIVE
135 #endif
136 #if defined(RECEIVE) | defined(CAPTURE)
137 static PARAMETER_CONST unsigned long beginTimeout = DEFAULT_BEGINTIMEOUT; // milliseconds
139 #endif
140 
141 #ifdef RECEIVE
142 #ifdef IRRECEIVER_2_PIN
143 static PARAMETER_CONST uint8_t receiverNo = 1;
144 #else
145 static const uint8_t receiverNo = 1;
146 #endif
147 #endif
148 
149 #ifdef ETHERNET
150 EthernetServer server(PORT);
151 #endif // ETHERNET
152 
153 #ifdef RESET
154 bool reset = false;
155 #endif
156 
157 #define modulesSupported EXPAND_AND_QUOTE(Base TRANSMIT_NAME CAPTURE_NAME RENDERER_NAME RECEIVE_NAME DECODER_NAME LED_NAME LCD_NAME PARAMETERS_NAME NAMED_COMMANDS_NAME PRONTO_NAME)
158 #ifndef PROGNAME
159 #define PROGNAME "AGirs"
160 #endif
161 #ifndef VERSION
162 #include "GirsLib/version.h"
163 #endif // VERSION
164 #define okString "OK"
165 #define errorString "ERROR"
166 #define timeoutString "."
167 
168 #ifdef TRANSMIT
169 
170 static bool sendIrSignal(const IrSignal &irSignal, unsigned int noSends=1) {
171  if (noSends == 0)
172  return false;
173 #ifdef TRANSMITLED
175 #endif
176  IrSender *irSender =
177 #ifdef NON_MOD
178  (irSignal.getFrequency() == 0) ? (IrSender*) new IrSenderNonMod(NON_MOD_PIN) :
179 #endif
180  (IrSender*) IrSenderPwm::getInstance(true);
181 
182  irSender->sendIrSignal(irSignal, noSends);
183 
184 #ifdef NON_MOD
185  if (irSignal.getFrequency() == 0)
186  delete irSender;
187  else
188 #endif
189  IrSenderPwm::deleteInstance();
190 
191 #ifdef TRANSMITLED
193 #endif
194  return true;
195 }
196 
197 #endif // TRANSMIT
198 
199 # if defined(RECEIVE) | defined(CAPTURE)
200 static void flushIn(Stream &stream UNUSED) {
201 #ifdef ARDUINO
202  while (stream.available())
203  stream.read();
204 #endif
205 }
206 #endif
207 
208 #ifdef RECEIVE
209 
210 static void decodeOrDump(IrReader *irReader, Stream& stream) {
211 #ifdef DECODER
212  MultiDecoder multiDecoder(*irReader);
213 #ifdef LCD
214  if (multiDecoder.getType() > MultiDecoder::noise) {
215  LedLcdManager::lcdPrint(multiDecoder.getType() == MultiDecoder::nec_ditto
216  ? "." : multiDecoder.getDecode(),
217  multiDecoder.getType() != MultiDecoder::nec_ditto);
218  if (multiDecoder.getType() == MultiDecoder::nec)
219  LedLcdManager::lcdSetCursor(0, 1); // prepare for dittos
220  }
221 #endif
222 
223 #ifdef DECODELED
225 #endif
226 #endif
227 
228 #if defined(DECODER) & ! defined(DONT_REPORT_DECODES) // lircd does its own decoding
229  switch (multiDecoder.getType()) {
230  case MultiDecoder::noise:
231  // ignore
232  break;
233  case MultiDecoder::undecoded:
234  irReader->dump(stream); // report data of undecoded signals
235  break;
236  default:
237  stream.println(multiDecoder.getDecode()); // also for timeout
238  break;
239  }
240 #else // ! (defined(DECODER) & ! defined(DONT_REPORT_DECODES))
241  if (irReader->isEmpty())
242  stream.println(F(timeoutString));
243  else
244  irReader->dump(stream);
245 #endif // !DECODER
246 }
247 
248 static bool receive(Stream& stream) {
249  IrReceiverSampler *irReceiver = IrReceiverSampler::getInstance();
250  if (irReceiver == NULL)
251  irReceiver = IrReceiverSampler::newIrReceiverSampler(captureSize,
253  if (irReceiver == NULL)
254  return false;
255  irReceiver->setEndingTimeout(receiveEndingTimeout);
256  irReceiver->setBeginningTimeout(beginTimeout);
257  irReceiver->setMarkExcess(IRRECEIVER_MARK_EXCESS);
258  flushIn(stream);
259 #ifdef RECEIVELED
261 #endif
262  irReceiver->enable();
263 #ifdef ARDUINO
264  while (!irReceiver->isReady() && stream.available() == 0)
265 #else
266  std::cout << "** Simulating timeout **" << std::endl;
267  delay(beginTimeout);
268 #endif
270  bool ready = irReceiver->isReady();
271  irReceiver->disable();
272 #ifdef RECEIVELED
274 #endif
275  if (ready)
276  decodeOrDump(irReceiver, stream);
277  IrReceiverSampler::deleteInstance();
278  return true;
279 }
280 #endif // RECEIVE
281 
282 #ifdef CAPTURE
283 
284 static bool capture(Stream& stream) {
285  IrWidget *irWidget = IrWidgetAggregating::newIrWidgetAggregating(captureSize,
287  if (irWidget == NULL)
288  stream.println(F("This cannot happen"));
289  irWidget->setEndingTimeout(captureEndingTimeout);
290  irWidget->setBeginningTimeout(beginTimeout);
291  irWidget->setMarkExcess(IRSENSOR_MARK_EXCESS);
292  irWidget->reset();
293 #ifdef CAPTURELED
295 #endif
296  flushIn(stream);
297 #ifdef ARDUINO
298  irWidget->capture();
299 #else
300  std::cout << "** Simulating timeout **" << std::endl;
301  delay(beginTimeout);
302 #endif
303 
304 #ifdef CAPTURELED
306 #endif
307  if (!irWidget->isEmpty()) {
308  // Trying to decode the capture does not make sense,
309  // that is what "receive" is for.
310  irWidget->dump(stream);
311  } else
312  stream.println(F(timeoutString));
313  IrWidgetAggregating::deleteInstance();
314  return true;
315 }
316 #endif // CAPTURE
317 
318 #ifdef NAMED_COMMANDS
319 // Defines a const IrNamedRemoteSet remoteSet with commands to be used.
320 //#include "my_named_remotes.inc"
321 extern const IrNamedRemoteSet remoteSet;
322 
323 static bool sendNamedCommand(Stream& stream, String& remoteName, String& commandName, unsigned int noSends) {
324  const IrNamedRemote* remote = remoteSet.getIrNamedRemote(remoteName.c_str());
325  if (remote == NULL) {
326  stream.println(F("No such remote"));
327  return false;
328  }
329 
330  const IrNamedCommand* command = remote->getIrNamedCommand(commandName.c_str());
331  if (command == NULL) {
332  stream.println(F("No such command"));
333  return false;
334  }
335  const IrSignal *irSignal = command->getIrSignal();
336  bool status = sendIrSignal(*irSignal, noSends); // waits, blinks
337  delete irSignal;
338  return status;
339 }
340 
341 static void dumpRemote(Stream& stream, String& name) {
342  if (name.length() == 0) {
343  for (unsigned int i = 0; i < remoteSet.getNoIrNamedRemotes(); i++) {
344  stream.print(remoteSet.getIrNamedRemotes()[i]->getName());
345  stream.print(" ");
346  }
347  stream.println();
348  } else {
349  const IrNamedRemote* remote = remoteSet.getIrNamedRemote(name.c_str());
350  if (remote == NULL)
351  stream.println(F("No such remote"));
352  else {
353  for (unsigned int i = 0; i < remote->getNoCommands(); i++) {
354  stream.print(remote->getAllCommands()[i]->getName());
355  stream.print(" ");
356  }
357  stream.println();
358  }
359  }
360 }
361 #endif
362 
363 void setup() {
367 #if defined(TRANSMIT)
368  // Make sure that sender is quiet (if reset or such)
369  IrSenderPwm::getInstance(true)->mute();
370 #endif
375 #ifdef LED
380 #endif
381 #ifdef LCD
382 #ifdef ETHERNET
383  LedLcdManager::lcdPrint(F("TCP"), false, 0, 2);
384 #ifdef SERIAL_DEBUG
385  LedLcdManager::lcdPrint(F(",SerialDbg"), false);
386 #endif
387 #else // ! ETHERNET
388  LedLcdManager::lcdPrint(F("Serial"), false, 0, 2);
389 #endif // ! ETHERNET
390 #endif // LCD
391 
392 #ifdef ETHERNET
393 #ifdef SDCARD_ON_ETHERSHIELD_PIN
394  // disable the SD card, as recommended in the doc
395  pinMode(SDCARD_ON_ETHERSHIELD_PIN, OUTPUT);
396  digitalWrite(SDCARD_ON_ETHERSHIELD_PIN, LOW);
397 #endif
398  byte mac[] = { MACADDRESS };
399 #ifdef DHCP
400  Ethernet.begin(mac);
401 #else // !DHCP
402  Ethernet.begin(mac, IPAddress(IPADDRESS), IPAddress(DNSSERVER), IPAddress(GATEWAY), IPAddress(SUBNETMASK));
403 #endif // !DHCP
404 
405  String ipstring = GirsUtils::ip2string(Ethernet.localIP());
406  LedLcdManager::lcdPrint(ipstring, false, 0, 3);
407 
408 #ifdef BEACON
409  Beacon::setup(PROGNAME, "DE-AD-BE-EF-FE-ED", "Utility", "www.harctoolbox.org",
410  "", "", "", "http://arduino/nosuchfile.html");
411 #endif
412 
413  server.begin();
414 
415 #endif // ETHERNET
416 
417 #if defined(ARDUINO) & !defined(ETHERNET) | defined(SERIAL_DEBUG)
418 
419  Serial.begin(SERIALBAUD);
420 #if defined(ARDUINO_AVR_LEONARDO) | defined(ARDUINO_AVR_MICRO)
421  while (!Serial)
422  ; // wait for serial port to connect. "Needed for Leonardo only"
423 #endif
424  Serial.println(F(PROGNAME " " VERSION));
425  Serial.setTimeout(SERIALTIMEOUT);
426 
427 #ifdef ETHERNET
428  Serial.println(Ethernet.localIP());
429 #endif
430 #endif // defined(ARDUINO) & !defined(ETHERNET) | defined(SERIAL_DEBUG)
431 }
432 
433 #ifdef INFO
434 void info(Stream& stream) {
435  stream.print("Board: ");
436 #ifdef ARDUINO_AVR_MEGA2560
437  stream.print(F("Arduino Mega2560"));
438 #elif defined(ARDUINO_AVR_NANO)
439  stream.print(F("Arduino Nano"));
440 #elif defined(ARDUINO_AVR_LEONARDO)
441  stream.print(F("Arduino Leonardo"));
442 #elif defined(ARDUINO_AVR_MINI)
443  stream.print(F("Arduino Leonardo"));
444 #elif defined(ARDUINO_AVR_UNO)
445  stream.print(F("Arduino Uno"));
446 #else
447  stream.print(F("Unknown"));
448 #endif
449 
450  stream.print(F(", CPU frequency: " EXPAND_AND_QUOTE(F_CPU)));
451 
452  stream.println();
453 }
454 #endif
455 
456 static inline bool isPrefix(const String& cmd, const char *string) {
457  return strncmp(cmd.c_str(), string, cmd.length()) == 0;
458 }
459 
460 static inline bool isPrefix(const char *string, const String& cmd) {
461  return strncmp(cmd.c_str(), string, strlen(string)) == 0;
462 }
463 
464 #ifdef ARDUINO
465 bool isPrefix(const String& cmd, const __FlashStringHelper *pstring) {
466  return strncmp_PF(cmd.c_str(), (uint_farptr_t) pstring, cmd.length()) == 0;
467 }
468 
469 bool isPrefix(const __FlashStringHelper *pstring, const String& cmd) {
470  return strncmp_PF(cmd.c_str(), (uint_farptr_t) pstring, strlen_PF((uint_farptr_t) pstring)) == 0;
471 }
472 #endif
473 
474 static String readCommand(Stream& stream) {
475 #if defined(COMMANDLED) & defined(LED)
477 #endif
478 
479 #ifdef ARDUINO
480  //flushIn(stream);
481  while (stream.available() == 0) {
483  }
484 
485  String line = stream.readStringUntil(EOLCHAR);
486  line.trim();
487 #else
488  (void) stream;
490  static char str[1000];
491  std::cin.getline(str, 1000);
492  if (std::cin.eof()) {
493  std::cout << "Bye!" << std::endl;
494  exit(0);
495  }
496  char *s = str;
497  while (isspace(*s))
498  s++;
499  while (isspace(s[strlen(s)-1]))
500  s[strlen(s)-1] = '\0';
501  String line(s);
502 #endif
503 
504 #if defined(DEBUG_CMD)
505  LedLcdManager::lcdPrint(line, true, 0, 0);
506 #endif
507 #if defined(COMMANDLED) & defined(LED)
509 #endif
510  return line;
511 }
512 
513 static bool processCommand(const String& line, Stream& stream) {
514 #ifdef ETHERNET
515  bool quit = false;
516 #endif
517  Tokenizer tokenizer(line);
518  String cmd = tokenizer.getToken();
519 
520  // Decode command
521  if (cmd.length() == 0) {
522  // empty command, do nothing
523  stream.println(F(okString));
524  } else
525 
526 #ifdef CAPTURE
527  if (cmd[0] == 'a' || cmd[0] == 'c') {
528  capture(stream);
529  } else
530 #endif // CAPTURE
531 
532 #ifdef LCD
533  if (isPrefix(cmd, F("lcd"))) { //LCD
534  String rest = tokenizer.getRest();
536  stream.println(F(okString));
537  } else
538 #endif // LCD
539 
540 #ifdef LED
541  if (isPrefix(cmd, F("led"))) {
542  pin_t no = (pin_t) tokenizer.getInt();
543  String value = tokenizer.getToken();
544  bool success = LedLcdManager::setLogicLed(no, value.c_str());
545  stream.println(success ? F(okString) : F(errorString));
546  } else
547 #endif // LED
548 
549  if (isPrefix(cmd, F("modules"))) {
550  stream.println(F(modulesSupported));
551  } else
552 
553 #ifdef FREEMEM
554  if (isPrefix(cmd, F("memory"))) {
555  stream.println(GirsUtils::freeRam());
556  } else
557 #endif
558 
559 #ifdef INFO
560  if (isPrefix(cmd, F("info"))) {
561  info(stream);
562  } else
563 #endif
564 
565 #ifdef PARAMETERS
566  if (cmd[0] == 'p') { // parameter
567  String variableName = tokenizer.getToken();
568  long value = tokenizer.getInt();
569  unsigned long *variable32 = NULL;
570  uint16_t *variable16 = NULL;
571  uint8_t *variable8 = NULL;
572 #if defined(RECEIVE) || defined(CAPTURE)
573  if (isPrefix(F("beg"), variableName))
574  variable32 = &beginTimeout;
575  else
576 #endif
577 #ifdef CAPTURE
578  if (isPrefix(F("capturee"), variableName))
579  variable32 = &captureEndingTimeout;
580 #endif
581 #ifdef RECEIVE
582  if (isPrefix(F("receivee"), variableName))
583  variable32 = &receiveEndingTimeout;
584  else
585 #endif
586 #if defined(RECEIVE) & defined(IRRECEIVER_2_PIN)
587  if (isPrefix(variableName, F("receiver")))
588  variable8 = &receiverNo;
589  else
590 #endif
591 #ifdef CAPTURE
592  if (isPrefix(F("captures"), variableName)) {
593  // TODO: check evenness of value
594  variable16 = &captureSize;
595  } else
596 #endif
597 #ifdef LED
598 #ifdef CONFIGURABLE_LEDS
599 #ifdef TRANSMITLED
600  if (isPrefix(F("transmitl"), variableName))
601  variable8 = &transmitled;
602  else
603 #endif
604 #ifdef CAPTURELED
605  if (isPrefix(F("capturel"), variableName))
606  variable8 = &captureled;
607  else
608 #endif
609 #ifdef RECEIVELED
610  if (isPrefix(F("receivel"), variableName))
611  variable8 = &receiveled;
612  else
613 #endif
614 #ifdef COMMANDLED
615  if (isPrefix(F("commandl"), variableName))
616  variable8 = &commandled;
617  else
618 #endif
619 #endif
620  // TODO: handle blinkTime. This currently means either break encapsulation
621  // of LedLcdManager, or write a nasty special case :-~
622 #endif
623  {
624  }
625 
626  if (variable32 != NULL) {
627  if (value != Tokenizer::invalid)
628  *variable32 = value;
629 
630  GirsUtils::printVariable(stream, variableName.c_str(), *variable32);
631  } else if (variable16 != NULL) {
632  if (value != Tokenizer::invalid)
633  *variable16 = (uint16_t) value;
634 
635  GirsUtils::printVariable(stream, variableName.c_str(), *variable16);
636  } else if (variable8 != NULL) {
637  if (value != Tokenizer::invalid)
638  *variable8 = (uint8_t) value;
639 
640  GirsUtils::printVariable(stream, variableName.c_str(), *variable8);
641  } else
642  stream.println(F("No such variable"));
643  } else
644 #endif // PARAMETERS
645 
646 #ifdef ETHERNET
647  if (cmd[0] == 'q') { // quit
648  quit = true;
649  } else
650 #endif
651 
652 #ifdef RECEIVE
653  // TODO: option for force decoding off
654  if (isPrefix(cmd, F("receive"))) { // receive
655  bool status = receive(stream);
656  if (!status)
657  stream.println(F(errorString));
658  } else
659 #endif // RECEIVE
660 
661 #ifdef NAMED_COMMANDS
662  if (cmd[0] == 'n') {
663  uint16_t noSends = (uint16_t) tokenizer.getInt();
664  String remoteName = tokenizer.getToken();
665  String commandName = tokenizer.getToken();
666  bool success = sendNamedCommand(stream, remoteName, commandName, noSends);
667  if (success)
668  stream.println(okString);
669  } else
670 
671  if (isPrefix(cmd, "remote")) {
672  String name = tokenizer.getToken();
673  dumpRemote(stream, name);
674  } else
675 #endif
676 
677 #ifdef RESET
678  if (isPrefix(cmd, "reset")) {
679  reset = true;
680  } else
681 #endif
682 
683 #ifdef TRANSMIT
684  if (cmd[0] == 's') { // send
685  // TODO: handle unparsable data gracefully
686  uint16_t noSends = (uint16_t) tokenizer.getInt();
687  frequency_t frequency = tokenizer.getFrequency();
688  uint16_t introLength = (uint16_t) tokenizer.getInt();
689  uint16_t repeatLength = (uint16_t) tokenizer.getInt();
690  uint16_t endingLength = (uint16_t) tokenizer.getInt();
691  microseconds_t intro[introLength];
692  microseconds_t repeat[repeatLength];
693  microseconds_t ending[endingLength];
694  for (uint16_t i = 0; i < introLength; i++)
695  intro[i] = tokenizer.getMicroseconds();
696  for (uint16_t i = 0; i < repeatLength; i++)
697  repeat[i] = tokenizer.getMicroseconds();
698  for (uint16_t i = 0; i < endingLength; i++)
699  ending[i] = tokenizer.getMicroseconds();
700  IrSignal irSignal(intro, introLength, repeat, repeatLength, ending, endingLength, frequency);
701  bool status = sendIrSignal(irSignal, noSends); // waits
702  stream.println(status ? F(okString) : F(errorString));
703  } else
704 #endif // TRANSMIT
705 
706 #ifdef PRONTO
707  if (isPrefix(cmd, F("hex"))) { // pronto hex send
708  uint16_t noSends = (uint16_t) tokenizer.getInt();
709  String rest = tokenizer.getRest();
710  IrSignal *irSignal = Pronto::parse(rest.c_str());
711  bool status = false;
712  if (irSignal != NULL) {
713  status = sendIrSignal(*irSignal, noSends); // waits
714  delete irSignal;
715  }
716  stream.println(status ? F(okString) : F(errorString));
717  } else
718 #endif // PRONTO
719 
720 #ifdef RENDERER
721  if (cmd[0] == 't') { // transmit
722  // TODO: handle unparseable data gracefully
723  uint16_t noSends = (uint16_t) tokenizer.getInt();
724  String protocol = tokenizer.getToken();
725  const IrSignal *irSignal = NULL;
726  if (isPrefix(protocol, F("nec1"))) {
727  unsigned int D = (unsigned) tokenizer.getInt();
728  unsigned int S = (unsigned) tokenizer.getInt();
729  unsigned int F = (unsigned) tokenizer.getInt();
730  irSignal = (F == Tokenizer::invalid)
731  ? Nec1Renderer::newIrSignal(D, S)
732  : Nec1Renderer::newIrSignal(D, S, F);
733  } else if (isPrefix(protocol, F("rc5"))) {
734  unsigned int D = (unsigned) tokenizer.getInt();
735  unsigned int F = (unsigned) tokenizer.getInt();
736  unsigned int T = (unsigned) tokenizer.getInt();
737  irSignal = (T == Tokenizer::invalid)
738  ? Rc5Renderer::newIrSignal(D, F)
739  : Rc5Renderer::newIrSignal(D, F, T);
740  } else {
741  stream.print(F("no such protocol: "));
742  stream.println(protocol);
743  }
744  bool status = false;
745  if (irSignal != NULL) {
746  status = sendIrSignal(*irSignal, noSends); // waits, blinks
747  delete irSignal;
748  }
749  stream.println(status ? F(okString) : F(errorString));
750  } else
751 #endif // RENDERER
752 
753  if (cmd[0] == 'v') { // version
754  stream.println(F(PROGNAME " " VERSION));
755  } else {
756  stream.println(F(errorString));
757  }
758 
759  //flushIn(stream);
760 #ifdef RESET
761  if (reset)
762  return false;
763 #endif
764 
765 #ifdef ETHERNET
766  if (quit)
767  return false;
768 #endif
769 
770  return true;
771 }
772 
773 static bool readProcessOneCommand(Stream& stream) {
774  String line = readCommand(stream);
775 #ifdef SERIAL_DEBUG
776  Serial.println("Command: " + line);
777 #endif
778  return processCommand(line, stream);
779 }
780 
781 #if defined(ETHERNET)
782 bool readProcessOneTcpCommand(EthernetClient& client) {
783  while (client.available() == 0) {
785 #ifdef BEACON
786  Beacon::checkSend();
787 #endif
788  if (!client.connected())
789  return false;
790  }
791  return readProcessOneCommand(client);
792 }
793 #endif
794 
795 void loop() {
797 #ifdef ETHERNET
798 #ifdef BEACON
799  Beacon::checkSend();
800 #endif
801 
802  EthernetClient client = server.available();
803  if (!client)
804  return;
805  client.setTimeout(10000);
806 #ifdef LCD
807  LedLcdManager::lcdPrint(F("Connection from"), true, 0, 0);
808  String ip = GirsUtils::ip2string(client.remoteIP());
809  LedLcdManager::lcdPrint(ip, false, 0, 1);
810 #endif
811 #ifdef SERIAL_DEBUG
812  Serial.print(F("Connection from "));
813  Serial.println(ip);
814 #endif
815 #if defined(COMMANDLED) & defined(LED)
817 #endif
818 
819  while (readProcessOneTcpCommand(client))
820 #if defined(COMMANDLED) & defined(LED)
822 #endif
823  ;
824 #ifdef LCD
825  LedLcdManager::lcdPrint(F("Connection closed!"), true, 0, 0);
826 #endif
827 #ifdef SERIAL_DEBUG
828  Serial.println(F("Connection closed!"));
829 #endif
830  client.println(F("Bye"));
831 
832 #if defined(COMMANDLED) & defined(LED)
834 #endif
835 
836  if (client.connected())
837  client.flush();
838  client.stop();
839 
840 #else // ! ETHERNET
841 
842 #ifdef ARDUINO
843  Stream& stream = Serial;
844  #else
845  Stream stream(std::cout);
846 #endif
847  readProcessOneCommand(stream);
848 #endif // ! ETHERNET
849 
850 #ifdef RESET
851  if (reset) {
853  reset = false; // In case it does not work, do not keep trying
854  }
855 #endif
856 }
857 
858 #ifndef ARDUINO
859 int main() {
860  setup();
861  while (true)
862  loop();
863 }
864 #endif
microseconds_t getMicroseconds()
Definition: Tokenizer.cpp:92
static const unsigned sensorNo
Definition: Girs.cpp:131
#define okString
Definition: Girs.cpp:164
static bool receive(Stream &stream)
Definition: Girs.cpp:248
#define IRRECEIVER_MARK_EXCESS
This quantity is added to all gaps and subtracted from all marks when receiving.
#define LCD_HEIGHT
#define VERSION
Version of the current library.
Definition: version.h:6
#define LCD_I2C_ADDRESS
EthernetServer server(PORT)
static void setupReceivers()
Definition: GirsUtils.h:163
String getRest()
Definition: Tokenizer.cpp:43
static pin_t receiverPin(uint8_t receiverNo UNUSED)
Definition: GirsUtils.h:33
static void setupSensors()
Definition: GirsUtils.h:245
#define SIGNAL_LED_8
#define SERIALBAUD
Configured speed of the serial port.
#define captureled
#define transmitled
#define receiveled
static bool readProcessOneCommand(Stream &stream)
Definition: Girs.cpp:773
#define COMMANDLED
Number of logical LED to light when waiting for command.
static const int invalid
Definition: Tokenizer.h:26
#define SIGNAL_LED_7
#define SIGNAL_LED_5
User configuration file.
#define DEFAULT_CAPTURESIZE
Size of capture and receive arrays.
#define SIGNAL_LED_1
#define commandled
#define SIGNAL_LED_6
#define PORT
TCP port to use.
static void lcdSetCursor(uint8_t x=0, uint8_t y=0)
#define DEFAULT_CAPTURE_ENDINGTIMEOUT
By capture, time to wait before signal is considered ended.
#define LCD_WIDTH
static void setup(int8_t i2cAddress=-1, uint8_t columns=defaultLcdColumns, uint8_t rows=defaultLcdRows, const pin_t physicalLeds[maxLeds]=NULL, const led_t logicalLeds[maxLeds]=NULL, const bool shouldTimeOut[maxLeds]=NULL)
Sets up the instance, to be called before using the instance.
bool readProcessOneTcpCommand(EthernetClient &client)
Definition: Girs.cpp:782
static String ip2string(IPAddress ip)
Definition: GirsUtils.cpp:34
#define UNUSED
#define TRANSMITLED
Number of logical LED to light when transmission takings place.
#define RECEIVELED
Number of logical LED to light when waiting for reception.
#define EXPAND_AND_QUOTE(str)
static PARAMETER_CONST unsigned long receiveEndingTimeout
Definition: Girs.cpp:134
static const uint8_t receiverNo
Definition: Girs.cpp:145
static bool setLogicLed(led_t logicLed, LedState state)
static PARAMETER_CONST uint16_t captureSize
Definition: Girs.cpp:138
#define DEFAULT_RECEIVE_ENDINGTIMEOUT
By receive, time to wait before signal is considered ended.
#define SIGNAL_LED_3
static void setupLedGroundPins()
#define LED_PARAMETER_CONST
Definition: Girs.cpp:100
static void flushIn(Stream &stream UNUSED)
Definition: Girs.cpp:200
static PARAMETER_CONST unsigned long captureEndingTimeout
Definition: Girs.cpp:130
uint8_t led_t
Definition: LedLcdManager.h:10
#define SIGNAL_LED_2
static void reset()
Definition: GirsUtils.cpp:21
#define timeoutString
Definition: Girs.cpp:166
static void setupShouldTimeout(led_t logicLed, bool state)
static IrReceiver * irReceiver
Definition: Listener.cpp:42
frequency_t getFrequency()
Definition: Tokenizer.cpp:97
static void decodeOrDump(IrReader *irReader, Stream &stream)
Definition: Girs.cpp:210
#define SIGNAL_LED_4
#define EOLCHAR
Character that ends the command lines.
#define modulesSupported
Definition: Girs.cpp:157
String getToken()
Definition: Tokenizer.cpp:69
static bool processCommand(const String &line, Stream &stream)
Definition: Girs.cpp:513
#define MACADDRESS
Must define MAC-Address to use here (!!).
static bool isPrefix(const String &cmd, const char *string)
Definition: Girs.cpp:456
static void lcdPrint(String &string, bool clear=true, int x=0, int y=-1)
static void printVariable(Stream &stream, const char *variableName, unsigned long value)
Definition: GirsUtils.h:23
#define CAPTURELED
Number of logical LED to light when waiting for capture.
void loop()
Definition: Girs.cpp:795
static bool sensorPullup(uint8_t sensorNo UNUSED)
Definition: GirsUtils.h:327
#define NON_MOD_PIN
Definition: GirsUtils.h:372
static void selfTest(const char *text)
#define SERIALTIMEOUT
Timeout for serial line.
#define IRSENSOR_MARK_EXCESS
This quantity is added to all gaps and subtracted from all marks when capturing.
#define PARAMETER_CONST
Definition: Girs.cpp:108
#define SDCARD_ON_ETHERSHIELD_PIN
Pin to disable (put low) on Ethernet shield.
#define PROGNAME
Definition: Girs.cpp:159
static void checkTurnoff()
Turn off if it is due.
static String readCommand(Stream &stream)
Definition: Girs.cpp:474
long getInt()
Definition: Tokenizer.cpp:87
#define DECODELED
Define to support blinking with LED according to decoding outcome.
#define DEFAULT_BEGINTIMEOUT
Time to wait for signal to start.
#define errorString
Definition: Girs.cpp:165
static bool capture(Stream &stream)
Definition: Girs.cpp:284
static PARAMETER_CONST unsigned long beginTimeout
Definition: Girs.cpp:137
static unsigned long freeRam()
Definition: GirsUtils.cpp:5
void setup()
Definition: Girs.cpp:363
static bool receiverPullup(uint8_t receiverNo UNUSED)
Definition: GirsUtils.h:77