22 #include <avr/pgmspace.h>
27 #include <IPAddress.h>
31 #include <IrReceiverSampler.h>
35 #include <IrSenderPwm.h>
39 #include <IrReceiverSampler.h>
43 #include <IrWidgetAggregating.h>
47 #include <IrSenderNonMod.h>
52 #error DECODER without RECEIVE is nonsensical, aborting.
54 #include <MultiDecoder.h>
59 #error RENDER without TRANSMIT is nonsensical, aborting.
62 #include <Nec1Renderer.h>
63 #include <Rc5Renderer.h>
67 #error NAMED_COMMANDS is presently not supported
79 #if defined(CONFIGURABLE_LEDS) & (! defined(PARAMETERS) | !defined(LED))
80 #error CONFIGURABLE_LEDS defined but not PARAMETERS and LED, aborting.
83 #ifdef CONFIGURABLE_LEDS
84 #define LED_PARAMETER_CONST
86 #define LED_PARAMETER_CONST const
90 #define PARAMETERS_NAME Parameters
91 #define PARAMETER_CONST
93 #define PARAMETERS_NAME
94 #define PARAMETER_CONST const
122 #if defined(RECEIVE) | defined(CAPTURE)
128 #ifdef IRRECEIVER_2_PIN
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)
145 #define PROGNAME "AGirs"
151 #define okString "OK"
152 #define errorString "ERROR"
153 #define timeoutString "."
162 static bool sendIrSignal(
const IrSignal &irSignal,
unsigned int noSends=1) {
170 (irSignal.getFrequency() == 0) ? (IrSender*)
new IrSenderNonMod(
NON_MOD_PIN) :
172 (IrSender*) IrSenderPwm::getInstance(
true);
174 irSender->sendIrSignal(irSignal, noSends);
177 if (irSignal.getFrequency() == 0)
181 IrSenderPwm::deleteInstance();
192 while (stream.available())
200 MultiDecoder multiDecoder(*irReader);
202 if (multiDecoder.getType() > MultiDecoder::noise) {
204 ?
"." : multiDecoder.getDecode(),
205 multiDecoder.getType() != MultiDecoder::nec_ditto);
206 if (multiDecoder.getType() == MultiDecoder::nec)
216 #if defined(DECODER) & ! defined(DONT_REPORT_DECODES)
217 switch (multiDecoder.getType()) {
218 case MultiDecoder::noise:
221 case MultiDecoder::undecoded:
222 irReader->dump(stream);
226 stream.println(multiDecoder.getDecode());
230 if (irReader->isEmpty())
233 irReader->dump(stream);
240 IrReceiverSampler *
irReceiver = IrReceiverSampler::getInstance();
255 while (!
irReceiver->isReady() && stream.available() == 0)
264 IrReceiverSampler::deleteInstance();
272 IrWidget *irWidget = IrWidgetAggregating::newIrWidgetAggregating(
captureSize,
274 if (irWidget ==
nullptr)
275 stream.println(F(
"This cannot happen"));
289 if (!irWidget->isEmpty()) {
292 irWidget->dump(stream);
296 IrWidgetAggregating::deleteInstance();
301 #ifdef NAMED_COMMANDS
305 static bool sendNamedCommand(Stream& stream,
const char* remoteName,
const char* commandName,
unsigned int noSends) {
307 if (remote ==
nullptr) {
308 stream.println(F(
"No such remote"));
313 if (command ==
nullptr) {
314 stream.println(F(
"No such command"));
318 bool status = sendIrSignal(*irSignal, noSends);
323 static void dumpRemote(Stream& stream,
const char* name) {
324 if (name[0] !=
'\0') {
326 stream.print(remote.
getName());
331 const IrNamedRemote* remote = remoteSet.getIrNamedRemote(name);
332 if (remote ==
nullptr)
333 stream.println(F(
"No such remote"));
336 stream.print(command.
getName());
349 #if defined(TRANSMIT)
351 IrSenderPwm::getInstance(
true)->mute();
353 #pragma GCC diagnostic push
354 #pragma GCC diagnostic ignored "-Wpedantic"
359 #pragma GCC diagnostic pop
378 #ifdef SDCARD_ON_ETHERSHIELD_PIN
387 Ethernet.begin(mac, IPAddress(IPADDRESS), IPAddress(DNSSERVER), IPAddress(GATEWAY), IPAddress(SUBNETMASK));
390 sprintf(ipstring,
"%d.%d.%d.%d", Ethernet.localIP()[0], Ethernet.localIP()[1], Ethernet.localIP()[2], Ethernet.localIP()[3]);
395 strcpy(url,
"http://");
396 strcat(url, ipstring);
405 #if ! defined(ETHERNET) | defined(SERIAL_DEBUG)
415 Serial.println(Ethernet.localIP());
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"));
434 stream.print(F(
"Unknown"));
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;
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;
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;
456 #pragma GCC diagnostic pop
459 #if defined(COMMANDLED) & defined(LED)
464 while (parser.
getStream().available() == 0)
470 #if defined(DEBUG_CMD)
473 #if defined(COMMANDLED) & defined(LED)
484 if (cmd[0] ==
'\0') {
490 if (cmd[0] ==
'a' || cmd[0] ==
'c') {
497 constexpr
size_t buflen = 40U;
507 pin_t no =
static_cast<pin_t
>(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))
545 if (
isPrefix(F(
"capturee"), variableName))
549 if (
isPrefix(F(
"receivee"), variableName))
553 #if defined(RECEIVE) & defined(IRRECEIVER_2_PIN)
554 if (
isPrefix(variableName, F(
"receiver")))
559 if (
isPrefix(F(
"captures"), variableName)) {
565 #ifdef CONFIGURABLE_LEDS
567 if (
isPrefix(F(
"transmitl"), variableName))
572 if (
isPrefix(F(
"capturel"), variableName))
577 if (
isPrefix(F(
"receivel"), variableName))
582 if (
isPrefix(F(
"commandl"), variableName))
593 if (variable32 !=
nullptr) {
598 }
else if (variable16 !=
nullptr) {
600 *variable16 =
static_cast<uint16_t
>(value);
603 }
else if (variable8 !=
nullptr) {
605 *variable8 = (uint8_t) value;
609 stream.println(F(
"No such variable"));
628 #ifdef NAMED_COMMANDS
630 uint16_t noSends =
static_cast<uint16_t
>(parser.
parseAbsInt());
635 bool success = sendNamedCommand(stream, remoteName, commandName, noSends);
643 dumpRemote(stream, name);
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];
663 microseconds_t *repeat =
new microseconds_t[repeatLength];
665 microseconds_t *ending =
new microseconds_t[endingLength];
667 IrSignal irSignal(intro, introLength, repeat, repeatLength, ending, endingLength, frequency);
668 bool status = sendIrSignal(irSignal, noSends);
676 uint16_t noSends =
static_cast<uint16_t
>(parser.
parseAbsInt());
680 if (irSignal !=
nullptr) {
681 status = sendIrSignal(*irSignal, noSends);
692 uint16_t noSends =
static_cast<uint16_t
>(parser.
parseAbsInt());
693 constexpr
size_t buflen = 20U;
694 char 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());
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());
711 ? Rc5Renderer::newIrSignal(D, F)
712 : Rc5Renderer::newIrSignal(D, F, T);
714 stream.print(F(
"no such protocol: "));
715 stream.println(protocol);
718 if (irSignal !=
nullptr) {
719 status = sendIrSignal(*irSignal, noSends);
753 Serial.print(F(
"Command: "));
760 #if defined(ETHERNET)
762 while (client.available() == 0) {
767 if (!client.connected())
781 EthernetClient client =
server.available();
784 client.setTimeout(10000);
788 sprintf(ip,
"%d.%d.%d.%d", Ethernet.localIP()[0], Ethernet.localIP()[1], Ethernet.localIP()[2], Ethernet.localIP()[3]);
792 Serial.print(F(
"Connection from "));
795 #if defined(COMMANDLED) & defined(LED)
800 #if defined(COMMANDLED) & defined(LED)
808 Serial.println(F(
"Connection closed!"));
810 client.println(F(
"Bye"));
812 #if defined(COMMANDLED) & defined(LED)
816 if (client.connected())
822 Stream& stream = Serial;
#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.
static bool receive(StreamParser &parser)
static bool readProcessOneCommand(Stream &stream)
static bool capture(Stream &stream)
static PARAMETER_CONST unsigned long beginTimeout
EthernetServer server(PORT)
static void flushIn(Stream &stream)
static PARAMETER_CONST unsigned long receiveEndingTimeout
static void readCommand(char *cmd, size_t cmdLength, StreamParser &parser)
static bool isPrefix(const char *string, const char *cmd)
static PARAMETER_CONST uint16_t captureSize
static const uint8_t receiverNo
#define LED_PARAMETER_CONST
static void decodeOrDump(IrReader *irReader, Stream &stream)
static constexpr size_t cmdLength
Allocated length (-1) for commands etc.
bool readProcessOneTcpCommand(EthernetClient &client)
static bool processCommand(const char *cmd, StreamParser &parser)
static PARAMETER_CONST unsigned long captureEndingTimeout
static const unsigned sensorNo
static IrReader * irReceiver
static void printVariable(Stream &stream, const char *variableName, unsigned long value)
static bool sensorPullup(uint8_t sensorNo UNUSED)
static unsigned long freeRam()
static void setupSensors()
static pin_t receiverPin(uint8_t receiverNo UNUSED)
static bool receiverPullup(uint8_t receiverNo UNUSED)
static void setupReceivers()
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.
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
#define EXPAND_AND_QUOTE(str)
#define VERSION
Version of the current library.