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