/*Paste your code here*/
#include <Arduino.h>
#include <string.h>
#define UNIT_TEST // Uncomment ONLY for unit testing
#ifdef UNIT_TEST
#include <ArduinoUnit.h>
#endif
#define LED_PIN 7
#define ADC_PIN A0
#define VCC 5.0
#define RX_BUFFER_SIZE 64
char rxBuffer[RX_BUFFER_SIZE];
char txBuffer[64];
uint8_t rxIndex = 0;
unsigned long startMillis;
bool ledState = false;
/* ===== Function Prototypes ===== */
bool processCommand(const char *cmd);
void sendSysOnTime(void);
void sendAdcValue(void);
void sendAdcVoltage(void);
/* ===== Command Lookup Table ===== */
typedef struct {
const char *cmd;
void (*handler)(void);
} AT_Command;
/* ===== Command Handlers ===== */
void cmdAT() {
strcpy(txBuffer, "OK");
}
void cmdLedOn() {
#ifndef UNIT_TEST
digitalWrite(LED_PIN, HIGH);
#endif
ledState = true;
strcpy(txBuffer, "+LED:\"ON\"");
}
void cmdLedOff() {
#ifndef UNIT_TEST
digitalWrite(LED_PIN, LOW);
#endif
ledState = false;
strcpy(txBuffer, "+LED:\"OFF\"");
}
void cmdLedStatus() {
strcpy(txBuffer, ledState ? "+LED_STATUS:\"ON\"" : "+LED_STATUS:\"OFF\"");
}
void cmdSysOnTime() {
sendSysOnTime();
}
void cmdAdcValue() {
sendAdcValue();
}
void cmdAdcVoltage() {
sendAdcVoltage();
}
/* ===== Lookup Table ===== */
AT_Command commandTable[] = {
{ "AT", cmdAT },
{ "AT+LED=ON", cmdLedOn },
{ "AT+LED=OFF", cmdLedOff },
{ "AT+LED_STATUS?", cmdLedStatus },
{ "AT+SYS_ON_TIME?", cmdSysOnTime },
{ "AT+ADC_VALUE?", cmdAdcValue },
{ "AT+ADC_VOLTAGE?", cmdAdcVoltage }
};
const uint8_t commandCount = sizeof(commandTable) / sizeof(commandTable[0]);
/* ===== Setup ===== */
void setup() {
Serial.begin(9600);
#ifndef UNIT_TEST
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
#endif
startMillis = millis();
}
/* ===== UART Task (Production Only) ===== */
void uartTask(void) {
while (Serial.available()) {
char ch = Serial.read();
if (ch == '\n' || ch == '\r') {
if (rxIndex > 0) {
rxBuffer[rxIndex] = '\0';
processCommand(rxBuffer);
Serial.println(txBuffer);
rxIndex = 0;
}
} else if (rxIndex < RX_BUFFER_SIZE - 1) {
rxBuffer[rxIndex++] = ch;
}
}
}
/* ===== Loop ===== */
void loop() {
#ifndef UNIT_TEST
uartTask();
#else
Test::run();
#endif
}
/* ===== Command Processor ===== */
bool processCommand(const char *cmd) {
for (uint8_t i = 0; i < commandCount; i++) {
if (strcmp(cmd, commandTable[i].cmd) == 0) {
commandTable[i].handler();
return true;
}
}
strcpy(txBuffer, "ERROR");
return false;
}
/* ===== Utility Functions ===== */
void sendSysOnTime() {
unsigned long seconds = (millis() - startMillis) / 1000;
uint8_t hh = seconds / 3600;
uint8_t mm = (seconds % 3600) / 60;
uint8_t ss = seconds % 60;
sprintf(txBuffer, "+SYS_ON_TIME:\"%02u:%02u:%02u\"", hh, mm, ss);
}
void sendAdcValue() {
#ifdef UNIT_TEST
int value = 512; // mocked
#else
int value = analogRead(ADC_PIN);
#endif
sprintf(txBuffer, "+ADC_VALUE:%d", value);
}
void sendAdcVoltage() {
#ifdef UNIT_TEST
float voltage = 2.50; // mocked
#else
int adc = analogRead(ADC_PIN);
float voltage = (adc * VCC) / 1023.0;
#endif
sprintf(txBuffer, "+ADC_VOLTAGE:%.3f", voltage);
}
#ifdef UNIT_TEST
test(AT_OK) {
processCommand("AT");
assertEqual(txBuffer, "OK");
}
test(LED_ON) {
processCommand("AT+LED=ON");
assertTrue(ledState);
}
test(INVALID_CMD) {
processCommand("XYZ");
assertEqual(txBuffer, "ERROR");
}
#endif
Add a video of the output (know more)
Add a photo of your hardware showing the output.

Add a Screenshot of the serial terminal showing the output.
