Files
WII5Firmware/WII5Commands.cpp
scottp 295abb37ee Initial public release of WII5 Buoy firmware
Firmware for an autonomous wave-measurement buoy (ATmega2560-based
WII5 v2 board). Reads wave motion from a Sparton AHRS-M1/M2 IMU,
samples GPS and battery state, and reports back over Iridium SBD
satellite telemetry. Originally developed 2012-2024.

This is the first public release. Code, documentation, and field-tested
operating modes (Capture, Sleep, Position, ManualTest, SelfTest,
LowBattery) are licensed under Apache 2.0 — see LICENSE and NOTICE.

See README.md for an overview and build instructions, CONTRIBUTING.md
for how to contribute, and DEPLOYMENTS.md for the field-deployment log.
2026-05-07 16:27:18 +10:00

1505 lines
52 KiB
C++

// SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2012-2024 Scott Penrose <scottp@dd.com.au> and WII5 Buoy contributors
//
// This file is part of WII5 Buoy firmware.
// See LICENSE for full terms.
/**
* @file WII5Commands.cpp
* @brief Command protocol handler: parses and dispatches @-prefixed commands.
*/
/*
WII5Commands - Main ability to control the wave buoy
Command Inputs
* Hardware Buttons
Use Sh3dNodeIO -> processCmd
* Serial Console
Use console.available -> processConsole
* Radio
Use Sh3dNodeNetwork.available -> processCmd
* Iridium
Use TODO (not sure yet, now this works out we have waiting Iridium Messges)
Maybe just wii5Iridium.available and next?
Naming Convensions here:
* begin - called once, as usual
* loop, loop* - Get direct acccess to hardware, such as a serial port or radio
* process* - Do something with some data we already have
* parse* - Calculate some data from probably some raw strings
Flow of Data: Serial
wii5Commands.loop()
console.loop - Basic read serial port
console.processCmd - Calculate string, and CSV output
console.available - got something
-> wii5Commands.processConsole
Got "@"
-> wii5Commands.processConsoleCsv
*/
#include <Arduino.h>
#include <TimeLib.h>
#include <WII5.h>
#include <WII5Commands.h>
#include <WII5Strings.h>
#include <MemoryFree.h>
void WII5Commands::begin() {
disableButtons = 600000;
}
/*
injectCommand - literally inject a plain text command and process it
Injecting a command can look like this:
@WII5,setting,captureoptions,90,16400,40960
1234567890123456789012345678901234567890123
1 2 3 4
44 bytes - with overheads, could be over the 50
4 bytes - command - @WII5,setting,captureoptions
2 bytes - Minutes = 1440 (2 bytes) maximum
4 bytes - Binary data
2 bytes (maybe 4) - rows
12 bytes
*/
bool WII5Commands::injectCommand(char *sendCmd) {
console.log(LOG_INFO, F("Command Inject: %s"), sendCmd);
console.clearCommand();
// Send prefix @WII5,
console.processCmd('@');
console.processCmd('W');
console.processCmd('I');
console.processCmd('I');
console.processCmd('5');
console.processCmd(',');
// Send received command
for (uint16_t k = 0; k < strlen(sendCmd); k++) {
char myChar = sendCmd[k];
console.processCmd(myChar);
}
console.processCmd('\r');
console.processCmd('\n');
// Proess command now
return true;
}
bool WII5Commands::processBinData() {
// TODO hard coded?
/*
WII5_BINDATA_3* command = wii5BinData.getCommand(wii5BinaryIridium, 340);
if (command) {
console.log(LOG_ERROR, F("processBinData injecting BinData message - %s"), command->message);
injectCommand(command->message);
}
else
*/
if (strncmp_P(wii5BinaryIridium, (PGM_P) F("@WII5,"), 6) == 0) {
console.log(LOG_ERROR, F("processBinData original (wii5) - %s"), (char*)wii5BinaryIridium);
console.log(LOG_ERROR, F("processBinData injecting Text message (wii5) - %s"), (char*)wii5BinaryIridium + 6);
injectCommand((char*)wii5BinaryIridium + 6);
}
// TODO 2024 - Is this used - consider commenting out
else if (strncmp_P(wii5BinaryIridium, (PGM_P) F("@Maths,"), 7) == 0) {
// TODO: Area should have maths
setupLast(WII5DEVICE_UNKNOWN, WII5PORT_CONSOLE, WII5AREA_WII5, WII5COMMAND_NONE);
console.log(LOG_ERROR, F("processBinData original (maths) - %s"), (char*)wii5BinaryIridium);
console.log(LOG_ERROR, F("processBinData injecting Text message (maths) - %s"), (char*)wii5BinaryIridium + 7);
if (wii5Maths.queueCommand((char*)wii5BinaryIridium + 7, strlen(wii5BinaryIridium+7))) {
// Successfully queued message (max 2)
resultLast(WII5RESULTS_SUCCESS, F("MathsQueueSuccess"));
}
else {
// Failed to queue - report
resultLast(WII5RESULTS_INVALID, F("MathsQuueFailed"));
}
return true;
}
else {
console.log(LOG_ERROR, F("processBinData failed - no Command found in packet"));
return false;
}
// Command injected - time to process it
setupLast(WII5DEVICE_UNKNOWN, WII5PORT_CONSOLE, WII5AREA_WII5, WII5COMMAND_NONE);
if (processConsoleAT()) {
console.log(LOG_INFO, F("Command Inject: SUCCESS"));
// if ( (lastCommandCmd != WII5COMMAND_NONE) && (lastCommandResult != WII5RESULT_UNKNWON) ) {
// lastCommandResult = result;
// strncpy_P(lastCommandMessage, message, sizeof(lastCommandMessage));
return true;
}
else {
console.log(LOG_INFO, F("Command Inject: FAILED/NOT EXIST"));
return false;
}
}
bool WII5Commands::processNetwork() {
#ifdef WII5_RADIO_LORA
if (sh3dNodeNetwork.lastValid) {
switch(int(sh3dNodeNetwork.lastPacketType)) {
case SH3D_NODE_Packet_ConsoleReceive_packetType:
console.printf(F("# REMOTE RECEIVE: Level=%d"), sh3dNodeNetwork.localConsoleReceive->level);
console.printf(F(" message=%s"), sh3dNodeNetwork.localConsoleReceive->buf);
console.printNewLine();
// TODO setup last and runCommand
break;
default:
break;
};
}
#endif
return false;
}
// NOTE: Be careful this doesn't do much with the buttons, just inject into Console or similar
bool WII5Commands::processButtons() {
/* New option for keeping maths on? */
if (sh3dNodeIO.button2->isClicked()) {
console.log(LOG_INFO, F("Button2: clicked - turning on Maths CPU, hold 1h, return line on"));
// Turn on Maths. Hold maths on 1 hour. Set return line (force Maths to stay on)
wii5Maths.start(WII5MATHSMODE_BUTTON);
wii5Maths.setHold(3600);
wii5Maths.setReturnLine();
}
if (sh3dNodeIO.button2->isReleased()) {
console.log(LOG_INFO, F("Button2: released - turning off return line"));
wii5Maths.cancelReturnLine();
}
if (disableButtons < 30000) {
return false;
}
// Button still held for 10 minutes - disable it
else if (buttonActive && (buttonHeld > 600000)) {
buttonActive = false;
buttonReleased = false;
}
// Button released times up
else if (buttonReleased && (buttonReleaseWait > 500)) {
if (buttonHeld < WII5_BUTTON_HOLD_TIME) {
console.log(LOG_DEBUG, F("Button1: was held for < 5 seconds"));
}
else {
console.log(LOG_DEBUG, F("Button1: Released, switching mode"));
// Set default mode - set in config before.
wii5Controller.setDefaultMode();
// Optional - reboot
}
buttonActive = false;
buttonReleased = false;
buttonMode = 0;
}
// OUT: Two Beeps - tell you we detected it...
else if (sh3dNodeIO.button1->isClicked()) {
console.log(LOG_INFO, F("Button1: clicked"));
if (!buttonActive) {
buttonHeld = 0;
buttonActive = true;
buttonMode = 0;
console.log(LOG_DEBUG, F("Button1: pressed - hold for 10 seconds to get current mode"));
}
buttonReleased = false;
}
// RELEASE = Actiate what we just set
else if (sh3dNodeIO.button1->isReleased()) {
console.log(LOG_INFO, F("Button1: released"));
// We are in active state - wait
if (buttonActive) {
buttonReleaseWait = 0;
buttonReleased = true;
}
}
// Still held down, count the time
// TODO 2024 - Simplify this for WII5 2024
if (buttonActive) {
wii5Controller.shared5On();
// TODO if buttonActive for more then 5 mins. Disable button !
/*
0..4999 = Do nothing
> 5000 = Inc counter & show mode
> 10000 = Inc counter &
*/
if (buttonHeld > (uint32_t)((uint32_t)((uint32_t)buttonMode * (uint32_t)WII5_BUTTON_HOLD_TIME) + (uint32_t)WII5_BUTTON_HOLD_TIME)) {
buttonMode++;
switch(buttonMode) {
// Report Status
case 1:
wii5Maths.start(WII5MATHSMODE_BUTTON);
wii5Maths.setHold(900);
if (wii5Config.getDefaultMode() == WII5MODE_CAPTURE) {
// Capture = 3 beeps
sh3dNodeIO.led2Set(LED_TRIPPLE_LONG);
}
else {
// Sleep = 2 beeps
sh3dNodeIO.led2Set(LED_DOUBLE_LONG);
}
console.log(LOG_INFO, F("Button1: held - 2 = sleep, 3 = capturue, hold 10 seconds to troggle"));
break;
// Toggle Mode - then toggle back again if a mistake
case 2:
case 3:
wii5Maths.start(WII5MATHSMODE_BUTTON);
wii5Maths.setHold(900);
// NOTE: Onl default mode for now
if (wii5Config.getDefaultMode() == WII5MODE_CAPTURE) {
console.log(LOG_INFO, F("Button1: Swap - moving from to Sleep mode - please release button, buttonMode=%d"), buttonMode);
wii5Config.setDefaultMode(WII5MODE_SLEEP);
sh3dNodeIO.led2Set(LED_DOUBLE_LONG);
}
else {
console.log(LOG_INFO, F("Button1: Swap - moving from to Capture mode - please release button, buttonMode=%d"), buttonMode);
wii5Config.setDefaultMode(WII5MODE_CAPTURE);
sh3dNodeIO.led2Set(LED_TRIPPLE_LONG);
}
break;
case 4:
console.log(LOG_INFO, F("Button1: Shutdown stage - reseting in 5 seconds"));
wii5Setup.shutdownbeep();
wii5Maths.setHold(0);
wii5Maths.powerOff(true);
wii5Maths.stop();
// Force pins output low
pinMode(SHARED_5VOLT_PIN, OUTPUT);
digitalWrite(SHARED_5VOLT_PIN, LOW);
pinMode(POWER_MATHS_PIN, OUTPUT);
digitalWrite(POWER_MATHS_PIN, LOW);
wii5Config.resetConfigData();
// Wait for Pi shutdown 5 seconds, then reset us
wii5Controller.safeDelay(5000);
// TODO - how to stop this recurring forever if button fails on. Write to EEPROM
sh3dNodeUtil.reset();
break;
}
}
/*
else {
console.log(LOG_ERROR, F("buttonMode=%d, HOLD_TIME=%d, Held=%d"), buttonMode, WII5_BUTTON_HOLD_TIME, butonHeld)
if (buttonHeld > ((buttonMode * WII5_BUTTON_HOLD_TIME) + WII5_BUTTON_HOLD_TIME)) {
}
*/
}
#if BUTTON_3>0
if (sh3dNodeIO.button3->isClicked()) {
wii5Maths.gpioClick();
}
#endif
return false;
}
// setupLast - Need this before runCommand - e.g. if from Console vs Iridium
bool WII5Commands::runCommand(WII5_COMMANDS cmd, char** params, uint8_t paramsLen) {
setupLast(WII5DEVICE_UNKNOWN, WII5PORT_CONSOLE, WII5AREA_WII5, cmd);
// TODO returnLast
switch(cmd) {
case WII5COMMAND_NONE:
console.log(LOG_INFO, F("ERROR: @WII5 command, no match"));
return false;
break;
case WII5COMMAND_NA:
// Handled by another module... move along.
break;
case WII5COMMAND_HELP:
console.log(LOG_INFO, F("HELP: replaced with @Help"));
break;
case WII5COMMAND_ECHO:
// TODO reply with everythng after echo - up to X chars
break;
case WII5COMMAND_PEOPLE:
// TODO: reply with everything after echo - up to X chars
resultLast(WII5RESULTS_NOREPLY, F("No reply - people"));
resultLast(WII5RESULTS_NOREPLY, F("Scott Penrose <scottp@dd.com.au>"));
resultLast(WII5RESULTS_NOREPLY, F("WII5 Buoy firmware contributors"));
switch(console.getCsvVal(3)) {
case 0:
break;
}
break;
// HELLO Received - we need to send an ACK
case WII5COMMAND_HELLO:
// @WII5,hello,SourcePort,SourceDeviceType,SourceDeviceID,SourceSoftwareVersion
// @WII5,hello!,MyPort,MyDeviceType,MyDeviceID,MySoftwareVersion
// @WII5,hello,Console,Maths,100001,1
// NOTE: Device ID should be same both ends for Maths etc
console.log(LOG_DEBUG, F("Hello - port=%s, device=%s"),
console.getCsvBuffer(2),
console.getCsvBuffer(3)
);
wii5Maths.woops_on();
wii5Controller.setLastHello(
wii5Strings.parsePort(console.getCsvBuffer(2)),
wii5Strings.parseDevice(console.getCsvBuffer(3))
);
wii5Display.atCommandSend(F("hello!"), F("%S,%S,port=%S,device=%S,id=%lu,version=%S,board=%S,commit=%S,freeMemory=%d/%d"),
// Old way
F("console"),
F("wavebuoy"), // WII5_DEVICE_TYPE),
// New way
// 2 - port
F("console"),
// 3 - device
F("wavebuoy"), // WII5_DEVICE_TYPE),
// 4 - id
wii5Config.getDeviceId(),
// 5 - version
F(WII5_SOFTWARE_VERSION),
// 6 - Board
F(WII5_BOARD_NAME),
// 7 - Commit
F(WII5_SOFTWARE_COMMIT),
// TODO too long
// 8 - Free Memory / Max
freeMemory(), WII5_BOARD_MEMORY
/*
// 9 - Uptime
(uint32_t)(millis() / 60000),
// 10 - Current storage Record
wii5Config.getRecordCount(),
// 11 - mode
wii5Strings.strMode(wii5Controller.getMode())
*/
);
// Send DateTime if it is up to date and valid (we should also support RTC)
if (wii5Gps.isTimeValid()) {
console.log(LOG_DEBUG, F("Sending time - valid from GPS"));
wii5Display.atCommandSend(F("time"), F("%04d,%02d,%02d,%02d,%02d,%02d"),
int(year()), int(month()), int(day()),
int(hour()), int(minute()), int(second())
);
}
else {
console.log(LOG_DEBUG, F("Not sending time - not valid from GPS"));
}
// Send statusDump - useful information (short version)
wii5Controller.statusDump();
break;
case WII5COMMAND_HELLOACK:
console.log(LOG_DEBUG, F("COMMAND: hello Ack - Not implemented"));
wii5Maths.woops_on();
wii5Controller.setLastHello(
wii5Strings.parsePort(console.getCsvBuffer(2)),
wii5Strings.parseDevice(console.getCsvBuffer(3))
);
/*
console.printf(F("@WII5,hello!,Console,%S,%lu,%S"),
F(WII5_DEVICE_TYPE),
wii5Config.getDeviceId(),
F(WII5_SOFTWARE_VERSION)
);
*/
break;
// Sleep 30 seconds, loop 20 seconds - check we are basic WDT
case WII5COMMAND_WAITY:
console.log(LOG_FATAL, F("Sleep 30 seconds, then loop 20 using safe loop"));
wii5Setup.sleepBefore();
sh3dNodeUtil.sleep(30);
wii5Setup.sleepAfter();
for (uint8_t n = 0; n < 20; n++) {
console.log(LOG_FATAL, F("Safe Loop %d / 20"), n);
wii5Controller.safeDelay(1000);
}
// NOTE: No break, now do loop
// Unsafe loop 20 seconds - good for internal WDT testing
case WII5COMMAND_WAITX:
console.log(LOG_FATAL, F("ABOUT To loop (no other loops for 20 seconds)"));
for (uint8_t n = 0; n < 20; n++) {
console.log(LOG_FATAL, F("UNSAFE Loop %d"), n);
delay(1000);
}
console.log(LOG_FATAL, F("End of the 20 second loop"));
break;
// Unsafe 5 minutes - should cause external WDT reset
case WII5COMMAND_WAITZ:
console.log(LOG_FATAL, F("ABOUT To loop (no other loops for 300 seconds)"));
for (uint16_t n = 0; n < 300; n++) {
console.log(LOG_FATAL, F("UNSAFE Loop %d"), n);
delay(1000);
}
console.log(LOG_FATAL, F("End of the 300 second loop"));
break;
// Safe 5 minutes - Should not cause external WDT reset
case WII5COMMAND_WAITQ:
console.log(LOG_FATAL, F("ABOUT To loop (safe delay 300 seconds)"));
for (uint16_t n = 0; n < 300; n++) {
console.log(LOG_FATAL, F("Safe Loop %d"), n);
wii5Controller.safeDelay(1000);
}
console.log(LOG_FATAL, F("End of the 300 second loop"));
break;
// Sleep 5 miniutes - should not cause external WDT reset
case WII5COMMAND_WAITS:
console.log(LOG_FATAL, F("ABOUT To Sleep for 300 seconds to check WDT"));
wii5Setup.sleepBefore();
sh3dNodeUtil.sleep(300);
wii5Setup.sleepAfter();
console.log(LOG_FATAL, F("End of the 300 second sleep"));
break;
case WII5COMMAND_STATUS:
// TODO be nice to return status
// TODO move to dipslay ?
console.log(LOG_DEBUG, F("COMMAND: Status"));
wii5Controller.statusDump(true);
break;
case WII5COMMAND_LOG_DEBUG:
console.log(LOG_INFO, F("LOG: Level set to DEBUG - test with @WII5,log,test"));
console.setLevel(LOG_ALL);
break;
case WII5COMMAND_LOG_DEFAULT:
console.log(LOG_INFO, F("LOG: Level set to INFO - test with @WII5,log,test"));
console.setLevel(LOG_INFO);
break;
case WII5COMMAND_LOG_FATAL:
console.log(LOG_INFO, F("LOG: Level set to FATAL - test with @WII5,log,test"));
console.setLevel(LOG_INFO);
break;
case WII5COMMAND_LOG_ERROR:
console.log(LOG_INFO, F("LOG: Level set to ERROR - test with @WII5,log,test"));
console.setLevel(LOG_ERROR);
break;
case WII5COMMAND_LOG_TEST:
console.printf(F("# Log Level Fatal, Error, Warn, Info, Debug"));
console.log(LOG_FATAL, F("Using FATAL millis=%d"), millis());
console.log(LOG_ERROR, F("Using ERROR millis=%d"), millis());
console.log(LOG_WARN, F("Using WARN millis=%d"), millis());
console.log(LOG_INFO, F("Using INFO millis=%d"), millis());
console.log(LOG_DEBUG, F("Using DEBUG millis=%d"), millis());
break;
case WII5COMMAND_STORAGE_STATUS:
resultLast(WII5RESULTS_NOREPLY, F("No reply - SD Status"));
console.log(LOG_INFO, F("Storage: Current = %d"), wii5Controller.getSD());
break;
case WII5COMMAND_STORAGE_DEBUG:
resultLast(WII5RESULTS_NOREPLY, F("No reply Storage Debug"));
sdBlock.debug = (console.getCsvVal(3) > 0) ? true : false;
console.log(LOG_INFO, F("Storage: Debug = %d"), int(sdBlock.debug));
break;
case WII5COMMAND_STORAGE_SETSTATUS:
if (sdBlock.metadataUpdateStatus( // metadataBlock, mainRecordCount, 1);
console.getCsvVal(3), console.getCsvVal(4), console.getCsvVal(5)
)
) {
console.log(LOG_INFO, F("Storage: Status Field updated %lu,%lu,%lu"), console.getCsvVal(3), console.getCsvVal(4), console.getCsvVal(5));
resultLast(WII5RESULTS_SUCCESS, F("StatusUpdated"));
}
else {
console.log(LOG_INFO, F("Storage: Status Field updated %lu,%lu,%lu"), console.getCsvVal(3), console.getCsvVal(4), console.getCsvVal(5));
resultLast(WII5RESULTS_ERROR, F("StatusFailed"));
}
break;
case WII5COMMAND_STORAGE_OFF:
resultLast(WII5RESULTS_SUCCESS, F("SD Off"));
console.log(LOG_INFO, F("SD: off"));
wii5Controller.setSDOff();
break;
case WII5COMMAND_STORAGE_SD1:
wii5Controller.setSD1();
if (sdBlock.cardOpen(wii5Controller.getSD())) {
resultLast(WII5RESULTS_SUCCESS, F("SD 1 Open"));
console.log(LOG_INFO, F("SD: 1 - cardOpen - ON and Success"));
}
else {
resultLast(WII5RESULTS_ERROR, F("SD 1 Open"));
console.log(LOG_INFO, F("SD: 1 - cardOpen - Failure"));
}
break;
case WII5COMMAND_STORAGE_SD2:
wii5Controller.setSD2();
if (sdBlock.cardOpen(wii5Controller.getSD())) {
resultLast(WII5RESULTS_SUCCESS, F("SD 2 Open"));
console.log(LOG_INFO, F("SD: 2 - cardOpen - ON and Success"));
}
else {
resultLast(WII5RESULTS_ERROR, F("SD 2 Open"));
console.log(LOG_INFO, F("SD: 2 - cardOpen - Failure"));
}
break;
case WII5COMMAND_STORAGE_LIST:
resultLast(WII5RESULTS_NOREPLY, F("No reply - StorageList"));
sdBlock.metadataList(
console.getCsvVal(3),
console.getCsvVal(4) > 0 ? console.getCsvVal(4) : 20
);
break;
case WII5COMMAND_STORAGE_VIEW:
case WII5COMMAND_STORAGE_METADATA:
resultLast(WII5RESULTS_NOREPLY, F("No reply - Storage View"));
wii5Display.sdBlockView(console.getCsvVal(3), false, false);
break;
case WII5COMMAND_STORAGE_RESULTS:
resultLast(WII5RESULTS_NOREPLY, F("No reply - Storage Results"));
wii5Display.sdBlockView(console.getCsvVal(3), true, false);
break;
case WII5COMMAND_STORAGE_RAW:
resultLast(WII5RESULTS_NOREPLY, F("No reply - Storage Raw"));
wii5Display.sdBlockView(console.getCsvVal(3), true, true);
break;
case WII5COMMAND_STORAGE_FORMAT:
if (wii5Controller.getSD() != 0) {
console.log(LOG_ERROR, F("SD Card is still active, and format may effect running capture or maths processing"));
}
if (console.getCsvVal(3) == 1) {
wii5Controller.setSD1();
}
else if (console.getCsvVal(3) == 2) {
wii5Controller.setSD2();
}
else {
// FAIL - do not continue
resultLast(WII5RESULTS_INVALID, F("SD Format: SD Invalid")); // TODO get new size
return true;
}
if (sdBlock.cardOpen(wii5Controller.getSD(), true)) {
console.log(LOG_DEBUG, F("SD: %d - cardFormat - Open"), wii5Controller.getSD());
if (sdBlock.cardClose()) {
console.log(LOG_DEBUG, F("SD: %d - cardFormat - Complete"), wii5Controller.getSD());
if (console.getCsvVal(3) == 1)
resultLast(WII5RESULTS_SUCCESS, F("SD format: 1 Complete")); // TODO get new size
else
resultLast(WII5RESULTS_SUCCESS, F("SD format: 2 Complete")); // TODO get new size
}
else {
console.log(LOG_DEBUG, F("SD: %d - cardFormat - Failed format"), wii5Controller.getSD());
if (console.getCsvVal(3) == 1)
resultLast(WII5RESULTS_ERROR, F("SD Format Failed 1")); // TODO get new size
else
resultLast(WII5RESULTS_ERROR, F("SD Format Failed 2")); // TODO get new size
}
}
break;
// @WII5,setting,time,1988,01,28,01,02,03
case WII5COMMAND_SETTING_TIME:
when = now();
setTime(
int(console.getCsvVal(6)), int(console.getCsvVal(7)), int(console.getCsvVal(8)),
int(console.getCsvVal(5)), int(console.getCsvVal(4)), int(console.getCsvVal(3))
);
// Ignore anything less than 1 second (is there a way to do before setTime) (10 secconds)
// TODO configurable... 10 seconds safe?
// TODO abs - does it work with long
if ( ( (now() - when) > 10 ) || ( when - now() > 10) ) {
console.log(LOG_INFO, F("COMMAND: setTime RECEIVED = %04d-%02d-%02dT%02d:%02d:%02d - updating local and RTC"),
int(console.getCsvVal(3)), int(console.getCsvVal(4)), int(console.getCsvVal(5)),
int(console.getCsvVal(6)), int(console.getCsvVal(7)), int(console.getCsvVal(8))
);
#ifdef WII5_RTC
wii5RTC.setRTC(now());
#endif
}
break;
case WII5COMMAND_SETTING_LIST:
wii5Config.dump(true, NULL);
break;
case WII5COMMAND_SETTING_DEVICEID:
// TODO Move to function here for settings or bertter, to Config
console.log(LOG_INFO, F("COMMAND: Setting DeviceID = %lu"), console.getCsvVal(3));
// Limits - 10000 - 99999
if (console.getCsvVal(3) == 0) {
console.log(LOG_INFO, F("Support services"));
resultLast(WII5RESULTS_INVALID, F("ID: No ID"));
}
else if (
(console.getCsvVal(3) < 10000)
|| (console.getCsvVal(3) > 99999)
) {
console.log(LOG_ERROR, F("Unable to set DeviceID to '%lu' should be between 10000 - 99999"), console.getCsvVal(3));
resultLast(WII5RESULTS_INVALID, F("ID: Bad ID"));
}
else {
wii5Config.setDeviceId(console.getCsvVal(3));
lastCommandResult = WII5RESULTS_SUCCESS;
snprintf_P(
lastCommandMessage, sizeof(lastCommandMessage),
PSTR("ID: set=%lu"),
wii5Config.getDeviceId()
);
}
break;
case WII5COMMAND_SETTING_GPSTIMEOUT:
resultLast(WII5RESULTS_NOREPLY, F("No reply - gpstimeout")); // TODO Maybe?
console.log(LOG_INFO, F("COMMAND: Setting GPSTimeout = %lu"), console.getCsvVal(3));
if (console.getCsvVal(3) == 0) {
console.log(LOG_INFO, F("COMMAND: Existing GPSTimeout = %lu"), console.getCsvVal(3));
}
else if (
(console.getCsvVal(3) < 30)
|| (console.getCsvVal(3) > 900)
) {
console.log(LOG_ERROR, F("COMMAND: Unable to set GPSTimeouta"));
}
else {
wii5Config.setGpsTimeout(console.getCsvVal(3));
}
break;
case WII5COMMAND_SETTING_DEFAULTS:
console.log(LOG_INFO, F("COMMAND: Setting config back to defaults"));
if (console.getCsvVal(3) == 3759) {
console.log(LOG_INFO, F("COMMAND: reset counters = %lu"), console.getCsvVal(3));
wii5Config.resetCounters();
resultLast(WII5RESULTS_SUCCESS, F("CountersReset")); // TODO Maybe?
}
else {
// Reset Config Defaults... Then allow override
wii5Config.resetConfigData();
wii5Config.resetStatusData();
wii5Controller.statusDump();
resultLast(WII5RESULTS_SUCCESS, F("ConfigDefaults")); // TODO Maybe?
}
break;
case WII5COMMAND_SEND:
{
// Send any commands
// IMPORTANT - do not reply command here !
// strncpy(wii5Commands.lastCommandMessage, buf, bufSize < 235 ? bufSize, 235);
memset(wii5Commands.lastCommandMessage, 0, sizeof(wii5Commands.lastCommandMessage));
char *pos = wii5Commands.lastCommandMessage;
uint16_t used = 0;
for (uint8_t i = 2; i < console.getCsvCount(); i++) {
strncpy(pos, console.getCsvBuffer(i), sizeof(wii5Commands.lastCommandMessage) - used);
pos += strlen(console.getCsvBuffer(i));
used += strlen(console.getCsvBuffer(i));
if (used < sizeof(wii5Commands.lastCommandMessage)) {
*pos = ',';
pos++;
used++;
}
}
wii5Commands.lastCommandMessage[sizeof(wii5Commands.lastCommandMessage) - 1] = '\0';
console.log(LOG_FATAL, F("SEND Text Received: %s"), wii5Commands.lastCommandMessage);
wii5Communications.sendText();
}
break;
case WII5COMMAND_SET:
// Special case
// - set,capture,{period},{binary} - And set the default mode
// - set,sleep,{period},{binary},{until} - And set the default mode
{
WII5_MODES newMode;
newMode = wii5Strings.parseMode(console.getCsvBuffer(2));
if (newMode == WII5MODE_NONE) {
console.log(LOG_ERROR, F("COMMAND: Invalid mode '%s'"), console.getCsvBuffer(4));
resultLast(WII5RESULTS_INVALID, F("InvalidMode"));
}
else {
console.log(LOG_DEBUG, F("COMMAND: Parsed mode = %d (%s)"), newMode, wii5Strings.strMode(newMode));
switch(newMode) {
case WII5MODE_SLEEP:
wii5Config.setSleepPeriod(console.getCsvVal(3));
wii5Config.setSleepBinaryType(console.getCsvVal(4));
wii5Config.setDefaultMode(newMode);
lastCommandResult = WII5RESULTS_SUCCESS;
snprintf_P(
lastCommandMessage, sizeof(lastCommandMessage),
PSTR("M=sleep,P=%lu,D=%lu"),
wii5Config.getSleepPeriod(), wii5Config.getSleepBinaryType()
);
break;
case WII5MODE_CAPTURE:
wii5Config.setCapturePeriod(console.getCsvVal(3));
wii5Config.setCaptureBinaryType(console.getCsvVal(4));
wii5Config.setCaptureRecords(5120);
lastCommandResult = WII5RESULTS_SUCCESS;
wii5Config.setDefaultMode(newMode);
snprintf_P(
lastCommandMessage, sizeof(lastCommandMessage),
PSTR("M=capture,P=%lu,D=%lu"),
wii5Config.getCapturePeriod(), wii5Config.getCaptureBinaryType()
);
break;
case WII5MODE_POSITION:
wii5Config.setPositionPeriod(console.getCsvVal(3));
wii5Config.setPositionBinaryType(console.getCsvVal(4));
wii5Config.setDefaultMode(newMode);
lastCommandResult = WII5RESULTS_SUCCESS;
snprintf_P(
lastCommandMessage, sizeof(lastCommandMessage),
PSTR("M=position,P=%lu,D=%lu"),
wii5Config.getPositionPeriod(), wii5Config.getPositionBinaryType()
);
break;
default:
resultLast(WII5RESULTS_INVALID, F("Not sleep, position or capture"));
break;
};
console.log(LOG_FATAL, F("Default mode saved, updating current mode to match"));
wii5Controller.setDefaultMode();
}
}
break;
case WII5COMMAND_SETTING_MODE:
{
bool defMode = false;
time_t expires = 0;
if (strcmp_P(console.getCsvBuffer(3),(PGM_P) F("default")) == 0) {
console.log(LOG_INFO, F("COMMAND: Setting MODE=Defalut"));
defMode = true;
}
else {
console.log(LOG_INFO, F("COMMAND: Setting MODE=Temporary datetime=%s"), console.getCsvBuffer(3));
defMode = false;
// TODO Parse valid date time etc
// TODO Do we have a valid time. Woot !
// TODO Set expires in... (max 4 weeks?)
expires = 123;
}
WII5_MODES newMode;
if (strcmp_P(console.getCsvBuffer(4),(PGM_P) F("swap")) == 0) {
// NOTE: Onl default mode for now
if (wii5Config.getDefaultMode() == WII5MODE_CAPTURE) {
console.log(LOG_INFO, F("COMMAND: Swap - moving from Capture to Sleep mode"));
newMode = WII5MODE_SLEEP;
}
else {
console.log(LOG_ERROR, F("COMMAND: Swap - moving from to capture mode"));
newMode = WII5MODE_CAPTURE;
}
}
else {
newMode = wii5Strings.parseMode(console.getCsvBuffer(4));
}
if (newMode == WII5MODE_NONE) {
console.log(LOG_ERROR, F("COMMAND: Invalid mode '%s'"), console.getCsvBuffer(4));
resultLast(WII5RESULTS_INVALID, F("InvalidMode"));
}
else {
console.log(LOG_DEBUG, F("COMMAND: Parsed mode = %d (%s)"), newMode, wii5Strings.strMode(newMode));
if (defMode) {
console.log(LOG_INFO, F("Default mode set to = %d (%s)"), newMode, wii5Strings.strMode(newMode));
wii5Config.setDefaultMode(newMode);
resultLast(WII5RESULTS_SUCCESS, F("mode=")); // Add new mode
}
}
// IF mode=capture, optionally set Period and Binary Type
// IF mode=position, optionally set Periods and Binary Type
// IF mode=sleep???
console.log(LOG_FATAL, F("Default mode saved, updating current mode to match"));
wii5Controller.setDefaultMode();
wii5Maths.setHold(900);
}
break;
case WII5COMMAND_SETTING_BATTERYOPTIONS:
resultLast(WII5RESULTS_NOREPLY, F("No reply"));
console.log(LOG_INFO, F("COMMAND: Setting Battery Low=%lu, Mide=%lu"), console.getCsvVal(3), console.getCsvVal(4));
wii5Config.setBatteryLow(console.getCsvVal(3));
wii5Config.setBatteryMid(console.getCsvVal(4));
break;
case WII5COMMAND_SETTING_DISABLELOWBATTERY:
console.log(LOG_INFO, F("COMMAND: Setting Disable Low Battery = %lu"), console.getCsvVal(3));
/*
if (
(console.getCsvVal(3) < 10000)
|| (console.getCsvVal(3) > 99999)
) {
console.log(LOG_ERROR, F("Unable to set DeviceID to '%lu' should be between 10000 - 99999"), console.getCsvVal(3));
}
else {
}
*/
wii5Config.setDisableLowBattery(console.getCsvVal(3));
break;
case WII5COMMAND_SETTING_FLAGS:
// ALL or ONE
// wii5Config.setDisableLowBattery(console.getCsvVal(3));
break;
case WII5COMMAND_SETTING_CAPTUREOPTIONS:
console.log(LOG_INFO, F("COMMAND: Setting Capture Options Period=%lu minute, Flags=%lu, Records=%lu"), console.getCsvVal(3), console.getCsvVal(4), console.getCsvVal(5));
// TODO - do we need limits here too?
if (
(console.getCsvVal(3) >= 5) // 15 Minutes TODO 15
&& (console.getCsvVal(3) <= 720) // to 12 hours
) {
wii5Config.setCapturePeriod(console.getCsvVal(3));
}
// TODO Else error
if (console.getCsvVal(4) >= 0) {
wii5Config.setCaptureBinaryType(console.getCsvVal(4));
}
if (console.getCsvVal(5) >= 0) {
wii5Config.setCaptureRecords(console.getCsvVal(5));
}
break;
case WII5COMMAND_SETTING_POSITIONOPTIONS:
console.log(LOG_INFO, F("COMMAND: Setting Position Options = %lu,%lu"), console.getCsvVal(3), console.getCsvVal(4));
if (
(console.getCsvVal(3) >= 3) // 3 Minutes
&& (console.getCsvVal(3) <= 720) // to 12 hours
) {
wii5Config.setPositionPeriod(console.getCsvVal(3));
}
if (console.getCsvVal(4) >= 0) {
wii5Config.setPositionBinaryType(console.getCsvVal(4));
}
break;
case WII5COMMAND_SETTING_SLEEPOPTIONS:
console.log(LOG_INFO, F("COMMAND: Setting Sleep Options = %lu,%lu"), console.getCsvVal(3), console.getCsvVal(4));
if (
(console.getCsvVal(3) >= 2) // 2 minutes
&& (console.getCsvVal(3) <= 5760) // 4 days
) {
wii5Config.setSleepPeriod(console.getCsvVal(3));
}
if (console.getCsvVal(4) >= 0) {
wii5Config.setSleepBinaryType(console.getCsvVal(4));
}
break;
case WII5COMMAND_RESET:
if (console.getCsvVal(2) == 666) {
console.log(LOG_FATAL, F("COMMAND: Reset..."));
SerialConsole.flush();
sh3dNodeUtil.reset();
}
else {
console.log(LOG_FATAL, F("COMMAND: Reset failed.... did you know the code..."));
}
break;
#ifdef WII5_GPS
case WII5COMMAND_GPS_START:
console.log(LOG_INFO, F("GPS: Start"));
wii5Gps.on();
break;
case WII5COMMAND_GPS_STOP:
console.log(LOG_INFO, F("GPS: Stop"));
wii5Gps.off();
break;
case WII5COMMAND_GPS_DUMP:
console.log(LOG_INFO, F("GPS: Dump"));
wii5Gps.dump();
break;
case WII5COMMAND_GPS_PASSTHROUGH:
console.log(LOG_INFO, F("GPS: Passthrough set to %d"), console.getCsvVal(3));
wii5Gps.setPassthrough(console.getCsvVal(3) ? 1 : 0);
break;
case WII5COMMAND_GPS_DEBUG:
console.log(LOG_INFO, F("GPS: Debug set to %d"), console.getCsvVal(3));
wii5Gps.setDebug(console.getCsvVal(3) ? 1 : 0);
break;
case WII5COMMAND_GPS_TIME:
console.log(LOG_INFO, F("GPS: autoTime"));
wii5Gps.autoTime();
break;
case WII5COMMAND_GPS_POS:
console.log(LOG_INFO, F("GPS: autoPos"));
wii5Gps.autoPos();
break;
case WII5COMMAND_GPS_ACCURATE:
console.log(LOG_INFO, F("GPS: autoAccurate"));
wii5Gps.autoAccurate();
break;
#endif
case WII5COMMAND_SPARTON_MODE:
//TODO move logic to Sparton
console.log(LOG_DEBUG, F("COMMAND: SPARTON Mode - Not implemented"));
break;
case WII5COMMAND_SPARTON_DUMP:
//TODO move logic to Sparton
console.log(LOG_DEBUG, F("COMMAND: SPARTON Dump - Not implemented"));
break;
case WII5COMMAND_SPARTON_INFO:
console.log(LOG_DEBUG, F("COMMAND: SPARTON Info"));
wii5Sparton.info();
break;
case WII5COMMAND_SPARTON_PASSTHROUGH:
console.log(LOG_INFO, F("Sparton: Passthrough set to %d"), console.getCsvVal(3));
wii5Sparton.setPassthrough(console.getCsvVal(3) ? 1 : 0);
break;
case WII5COMMAND_SPARTON_DEBUG:
console.log(LOG_INFO, F("Sparton: Debug set to %d"), console.getCsvVal(3));
wii5Sparton.setDebug(console.getCsvVal(3) ? 1 : 0);
break;
// TODO @WII5,maths - seems in both directions. That is bad.
// TODO From Maths, should be @Maths not @WII5 or @WII5Maths or something
case WII5COMMAND_MATHS_BEEP:
wii5Maths.woops_on();
if(strcmp_P(console.getCsvBuffer(3),(PGM_P) F("once")) == 0) {
console.log(LOG_DEBUG, F("COMMAND: Maths Beep - once"));
wii5Controller.shared5On();
sh3dNodeIO.led2Set(LED_ONCE);
}
else if(strcmp_P(console.getCsvBuffer(3),(PGM_P) F("quiet")) == 0) {
// Special case - check the mode
wii5Controller.shared5On();
if (! wii5Maths.isMode(WII5MATHSMODE_AUTO)) {
console.log(LOG_DEBUG, F("COMMAND: Maths Beep - ONCE"));
sh3dNodeIO.led2Set(LED_ONCE);
}
else {
console.log(LOG_DEBUG, F("COMMAND: Maths Beep - NORMAL"));
sh3dNodeIO.led2Set(LED_SHORT_LONG);
}
}
else {
console.log(LOG_DEBUG, F("COMMAND: Maths Beep"));
wii5Controller.shared5On();
sh3dNodeIO.led2Set(LED_SHORT_LONG);
}
break;
case WII5COMMAND_MATHS_INFO:
resultLast(WII5RESULTS_SUCCESS, F("Info Queued"));
wii5Maths.woops_on();
console.log(LOG_INFO, F("MATHS: Info"));
wii5Maths.queueCommand("info", 8);
break;
case WII5COMMAND_MATHS_BOOTED:
console.log(LOG_DEBUG, F("MathsBooted - flag for moving on"));
wii5Maths.woops_on();
wii5Controller.setLastHello(WII5PORT_CONSOLE, WII5DEVICE_MATHS);
break;
case WII5COMMAND_MATHS_RETURN:
if (console.getCsvVal(3) == 0) {
console.log(LOG_INFO, F("Maths - RETURN line - OFF"));
wii5Maths.cancelReturnLine();
}
else if (console.getCsvVal(3) == 1) {
console.log(LOG_INFO, F("Maths - RETURN line - ON"));
wii5Maths.setReturnLine();
}
else {
console.log(LOG_INFO, F("Maths - RETURN line - Unknown"));
}
break;
case WII5COMMAND_MATHS_FLIP:
console.log(LOG_FATAL, F("COMMAND: Maths Flip (setting maths to hold 1 hour)"));
wii5Maths.setHold(3600);
wii5ModeCapture.flip();
wii5Controller.statusDump();
break;
case WII5COMMAND_MATHS_RESTART:
if(strcmp_P(console.getCsvBuffer(3),(PGM_P) F("start")) == 0) {
console.log(LOG_INFO, F("MATHS: REBOOT - start"));
}
else if(strcmp_P(console.getCsvBuffer(3),(PGM_P) F("stop")) == 0) {
console.log(LOG_INFO, F("MATHS: REBOOT - stop"));
}
else if(strcmp_P(console.getCsvBuffer(3),(PGM_P) F("update")) == 0) {
console.log(LOG_INFO, F("MATHS: REBOOT - rebooting in: %lu seconds"), console.getCsvVal(4));
}
else if(strcmp_P(console.getCsvBuffer(3),(PGM_P) F("now")) == 0) {
console.log(LOG_INFO, F("MATHS: REBOOT - rebooting now"));
}
break;
case WII5COMMAND_MATHS_START:
console.log(LOG_INFO, F("COMMAND: Maths Start"));
// TODO - Other?
wii5Maths.start(WII5MATHSMODE_COMMS);
wii5Controller.statusDump();
break;
case WII5COMMAND_MATHS_HALT:
case WII5COMMAND_MATHS_STOP:
console.log(LOG_INFO, F("COMMAND: Maths Stop/Halt"));
wii5Maths.stop();
wii5Controller.statusDump();
break;
case WII5COMMAND_MATHS_HOLD:
wii5Maths.woops_on();
console.log(LOG_INFO, F("COMMAND: Maths Hold %d seconds"), console.getCsvVal(3));
wii5Maths.setHold(console.getCsvVal(3));
wii5Controller.statusDump();
break;
case WII5COMMAND_MATHS_UNTIL:
console.log(LOG_INFO, F("COMMAND: Maths Until time"), console.getCsvVal(3));
wii5Maths.setMathsUntil(console.getCsvVal(3));
wii5Controller.statusDump();
break;
// TODO Need to start maths, make sure it is fullly working then send the command to Maths,do etc.
// TODO how to send responses in that case? - Multiple
case WII5COMMAND_MATHS_DO:
break;
case WII5COMMAND_MATHS_MAKE:
break;
case WII5COMMAND_MATHS_DONE:
wii5Maths.queueDone();
break;
case WII5COMMAND_MATHS_SCRIPT:
if (console.getCsvVal(3) == 1) {
console.log(LOG_INFO, F("Queue: test one,two"));
wii5Maths.queueCommand("test,one", 8);
wii5Maths.queueCommand("test,two", 8);
}
else if (console.getCsvVal(3) == 2) {
console.log(LOG_INFO, F("Queue: test one,two"));
wii5Maths.queueCommand("do,", 8);
wii5Maths.queueCommand("test,two", 8);
}
else if (console.getCsvVal(3) == 3) {
console.log(LOG_INFO, F("Queue: Maths recompile"));
wii5Maths.queueCommand("makeextra,-DDEBUG_BUILD=1", 25);
}
else {
console.log(LOG_INFO, F("Queue: Maths - bogus commands"));
wii5Maths.queueCommand("DoesNone", 8);
}
break;
case WII5COMMAND_DUMP:
//TODO move logic to Controller or Display !!!
console.log(LOG_INFO, F("COMMAND: Dump ALL - Not implemented"));
break;
// Network tools
case WII5COMMAND_NETWORK_ECHO:
//TODO move logic to Controller or Network
console.log(LOG_DEBUG, F("Network: sendEcho (CONSOLE)"));
#ifdef WII5_RADIO_LORA
sh3dNodeNetwork.sendEcho();
#endif
break;
case WII5COMMAND_NETWORK_ECHOACK:
//TODO move logic to Controller or Network
#ifdef WII5_RADIO_LORA
console.log(LOG_DEBUG, F("Network: sendACK (for Echo)"));
sh3dNodeNetwork.sendACK(SH3D_NODE_Packet_Echo_packetType_ACK, SH3D_NODE_Packet_Echo_packetVersion);
#endif
break;
case WII5COMMAND_NETWORK_FAKEECHO:
//TODO move logic to Controller or Network
#ifdef WII5_RADIO_LORA
console.log(LOG_DEBUG, F("Network: Faking an echo"));
// NOTE: Used to create Fake Packets - should be in a Test Library
// TODO move to RadioLoRa
sh3dNodeRadio.lastLength = sizeof(SH3D_NODE_Packet_Echo);
sh3dNodeNetwork.localEcho->header.node.nodeType = 1;
sh3dNodeNetwork.localEcho->header.node.nodeId = 2;
sh3dNodeNetwork.localEcho->packetType = SH3D_NODE_Packet_Echo_packetType;
sh3dNodeNetwork.localEcho->packetVersion = SH3D_NODE_Packet_Echo_packetVersion;
sh3dNodeNetwork.localEcho->key = 9;
sh3dNodeNetwork.localEcho->val = 3;
sh3dNodeRadio.lastValid = true;
#endif
break;
case WII5COMMAND_NETWORK_FAKEECHOACK:
//TODO move logic to Controller or Network
#ifdef WII5_RADIO_LORA
console.log(LOG_DEBUG, F("Network: Faking an echo ack"));
// NOTE: Used to create Fake Packets - should be in a Test Library
// TODO move to RadioLoRa
sh3dNodeRadio.lastLength = sizeof(SH3D_NODE_Packet_ACK);
sh3dNodeNetwork.localACK->header.node.nodeType = 1;
sh3dNodeNetwork.localACK->header.node.nodeId = 2;
sh3dNodeNetwork.localACK->packetType = SH3D_NODE_Packet_Echo_packetType_ACK;
sh3dNodeNetwork.localACK->packetVersion = SH3D_NODE_Packet_Echo_packetVersion;
sh3dNodeRadio.lastValid = true;
#endif
break;
case WII5COMMAND_CAPTURE_START:
console.log(LOG_DEBUG, F("Capture: ManualStart requested (if not already running)"));
wii5Controller.setMode(WII5MODE_CAPTURE);
wii5ModeCapture.start();
break;
case WII5COMMAND_CAPTURE_STOP:
console.log(LOG_DEBUG, F("Capture: ManualStop requested (if running)"));
wii5Controller.setMode(WII5MODE_CAPTURE);
wii5ModeCapture.stop();
break;
case WII5COMMAND_POSITION_START:
console.log(LOG_DEBUG, F("Position: ManualStart requested (if not already running)"));
wii5Controller.setMode(WII5MODE_POSITION);
wii5ModePosition.start();
break;
case WII5COMMAND_POSITION_STOP:
console.log(LOG_DEBUG, F("Position: ManualStop requested (if running)"));
wii5Controller.setMode(WII5MODE_POSITION);
wii5ModePosition.stop();
break;
case WII5COMMAND_POSITION_PASSTHROUGH:
console.log(LOG_DEBUG, F("Position: Passthrough toggle"));
wii5Gps.setPassthrough(console.getCsvVal(3) ? 1 : 0);
wii5Gps.setDebug(console.getCsvVal(3) ? 1 : 0);
wii5Iridium.setPassthrough(console.getCsvVal(3) ? 1 : 0);
wii5Iridium.setDebug(console.getCsvVal(3) ? 1 : 0);
break;
case WII5COMMAND_MODE_POSITION:
console.log(LOG_DEBUG, F("Set: Mode=Position"));
wii5Controller.setMode(WII5MODE_POSITION);
break;
case WII5COMMAND_MODE_MANUALTEST:
console.log(LOG_DEBUG, F("Set: Mode=ManualTest"));
wii5Controller.setMode(WII5MODE_MANUALTEST);
break;
case WII5COMMAND_MODE_SELFTEST:
console.log(LOG_DEBUG, F("Set: Mode=SelfTest"));
if (strcmp_P(console.getCsvBuffer(3),(PGM_P) F("frommaths")) == 0) {
wii5ModeSelfTest.setMode(WII5SM_FROMMATHS);
}
else if (strcmp_P(console.getCsvBuffer(3),(PGM_P) F("nomaths")) == 0) {
wii5ModeSelfTest.setMode(WII5SM_NOMATHS);
}
wii5Controller.setMode(WII5MODE_SELFTEST);
break;
// TODO This should realy be CURRENt, ie, it could be the temp one
case WII5COMMAND_MODE_DEFAULT:
console.log(LOG_DEBUG, F("Set: Mode=Default"));
wii5Controller.setDefaultMode();
break;
case WII5COMMAND_MODE_CAPTURE:
console.log(LOG_DEBUG, F("Set: Capture Mode"));
wii5Controller.setMode(WII5MODE_CAPTURE);
break;
case WII5COMMAND_MODE_SLEEP:
console.log(LOG_DEBUG, F("Set: Sleep Mode (Note: Maths hold set to 5 minutes)"));
wii5Controller.setMode(WII5MODE_SLEEP);
// We must have set this from serial, lets leave MAths hold 5 mins
wii5Maths.setHold(900);
break;
case WII5COMMAND_BINDATA_LIST:
// TODO Check if we need reply..., where to store it? New var I think
console.log(LOG_DEBUG, F("BinData: List"));
wii5BinData.showSizes(lastCommandMessage, WII5_RESULT_MESSAGE);
break;
case WII5COMMAND_BINDATA_SPLIT:
// TODO Check if we need reply..., where to store it? New var I think
console.log(LOG_DEBUG, F("BinData: Split"));
wii5BinData.showSplit(console.getCsvVal(3), (uint16_t)console.getCsvVal(4), lastCommandMessage, WII5_RESULT_MESSAGE);
break;
case WII5COMMAND_WEATHER_READ:
console.log(LOG_DEBUG, F("Weather: Reading temperature"));
wii5Weather_18B20.temperatureRead();
break;
case WII5COMMAND_WEATHER_TEST:
console.log(LOG_DEBUG, F("Weather: Test Loop"));
{
for (uint16_t wtest = 0; wtest < 100; wtest++) {
console.log(LOG_INFO, F("Weather: Test Loop: n=%d"), wtest);
wii5Weather_18B20.temperatureRead();
}
}
break;
case WII5COMMAND_IRIDIUM_SEND:
console.log(LOG_DEBUG, F("Iridium: Send Text"));
wii5Iridium.setPassthrough(1); // TODO Should be configurable
// TODO What text should be configurable
wii5Iridium.setText(F("Longer example text"));
wii5Iridium.requestSendText();
break;
case WII5COMMAND_COMMUNICATIONS_DISABLED:
console.log(LOG_DEBUG, F("Communication: Disabled"));
wii5Communications.setDisabled(console.getCsvVal(3) ? 1 : 0);
break;
case WII5COMMAND_COMMUNICATIONS_TEST:
console.log(LOG_DEBUG, F("Communication: Test - once through test mode"));
wii5Communications.setAutoMode();
wii5Communications.start();
wii5Communications.setTESTING();
break;
case WII5COMMAND_COMMUNICATIONS_SIGNAL:
console.log(LOG_DEBUG, F("Communication: Signal (SD Card change)"));
wii5Communications.signalSD();
break;
case WII5COMMAND_COMMUNICATIONS_START:
console.log(LOG_DEBUG, F("Communication: Start"));
wii5Communications.start();
break;
case WII5COMMAND_COMMUNICATIONS_STOP:
console.log(LOG_DEBUG, F("Communication: Stop"));
wii5Communications.stop();
break;
case WII5COMMAND_BATTERY_START:
console.log(LOG_DEBUG, F("Battery: start"));
wii5Battery.start();
break;
default:
console.log(LOG_INFO, F("Command @ not yet implemented = '%s'."), wii5Strings.strCommand(cmd));
return false;
break;
}
return true;
}
// doneLast - flag that the entry is now done.
void WII5Commands::doneLast() {
lastCommandAckComplete = true;
}
// setupLast - set original last entry data
// TODO - Manually need to set:
// lastCommandCmd = cmd; lastCommandParam1 = 0; lastCommandParam2 = 0; lastCommandParam3 = 0;
// lastCommandResult = WII5RESULTS_UNKNOWN; memset(&lastCommandMessage, 0, sizeof(lastCommandMessage));
void WII5Commands::setupLast(WII5_DEVICES device, WII5_PORTS port, WII5_AREAS area, WII5_COMMANDS cmd) {
if (!lastCommandAckComplete) {
console.log(LOG_DEBUG, F("Warning. Last message did not deliver and ACK, it will have been lost."));
// TODO Details - log whole of lastCommand
}
// When and Where
lastCommandAge = 0;
lastCommandT = now();
lastCommandDevice = device;
lastCommandPort = port;
lastCommandArea = area;
// Cleanup
lastCommandCmd = cmd;
lastCommandParam1 = 0;
lastCommandParam2 = 0;
lastCommandParam3 = 0;
// Results ?
lastCommandResult = WII5RESULTS_UNKNOWN;
memset(&lastCommandMessage, 0, sizeof(lastCommandMessage));
// ackComplete
lastCommandAckComplete = false;
}
void WII5Commands::resultLast(WII5_RESULTS result, const __FlashStringHelper *message) {
lastCommandResult = result;
strncpy_P(lastCommandMessage, (const char *)message, sizeof(lastCommandMessage));
}
void WII5Commands::resultLast(WII5_RESULTS result, char *message) {
lastCommandResult = result;
strncpy(lastCommandMessage, message, sizeof(lastCommandMessage));
}
void WII5Commands::resultLast(WII5_RESULTS result) {
lastCommandResult = result;
}
/*
// resultLast(...)
lastCommandResult = X
snprintf_P(
lastCommandMessage, sizeof(lastCommandMessage),
PSTR(""),
getDeviceId(), getRecordCount()
);
*/
// Work out that we have a WII5,X where X is the result
bool WII5Commands::processConsoleAT() {
if (!console.available() || (console.getCommand() != '@'))
return false;
// TODO repeat this for other systems - e.g. parsing network or iridium
if (strcmp_P(console.getCsvBuffer(0),(PGM_P) F("WII5")) == 0) {
return runCommand(
wii5Strings.parseCommand(
console.getCsvBuffer(1),
console.getCsvBuffer(2),
console.getCsvBuffer(3)
)
);
}
else if (strcmp_P(console.getCsvBuffer(0),(PGM_P) F("Help")) == 0) {
return wii5Help.processConsoleCsv();
}
return false;
}
// Return false if there IS a command and it was not handled
bool WII5Commands::processConsoleStandard() {
if (console.available()) {
switch(console.getCommand()) {
// Help - Low level help before full commands
case 'h':
case 'H':
console.log(LOG_INFO, F("WII5: Simplified command and help system"));
console.log(LOG_FATAL, F(" NOTE: you may need to enable logs @WII5,log,all"));
console.log(LOG_DEBUG, F(" See @Help for full commands"));
console.log(LOG_DEBUG, F(" * - show all pins"));
console.log(LOG_DEBUG, F(" @WII5,maths,start|stop - immediate start or stop"));
console.log(LOG_DEBUG, F(" @WII5,maths,hold,300 - hold for 5 minutes"));
console.log(LOG_DEBUG, F(" @WII5,mode,manualtest - Immediate switch to manual test mode"));
console.log(LOG_DEBUG, F(" @WII5,capture,start|stop - start or stop a capture, also switches mode"));
console.log(LOG_DEBUG, F(" @WII5,mode,sleep - sleep mode."));
console.log(LOG_DEBUG, F(" Z - force a reset now (must add 666)"));
console.log(LOG_DEBUG, F(" . - set default mode"));
console.log(LOG_DEBUG, F(" ? - Status"));
break;
// RESET. usual Z666;
case 'Z':
if (console.getVal() == 666) {
sh3dNodeUtil.reset();
}
break;
// T: for manualTest Mode
case 'T':
// TODO console.log(LOG_FATAL, F("Old testmode. Inbstead = @WII5,mode,manualtest !!!"));
console.log(LOG_FATAL, F("MANUALTEST"));
wii5Controller.setMode(WII5MODE_MANUALTEST);
break;
// s: Sleep mode
case 's':
console.log(LOG_ERROR, F("Old sleepmode. Inbstead = @WII5,mode,sleep !!!"));
break;
// C for CAPTURE Mode
case 'C':
console.log(LOG_ERROR, F("Old capturemode. Inbstead = @WII5,mode,capture, @WII5,capture,start, @WII5,capture,stop !!!"));
break;
case 'W':
// TODO Danger ! Move this elsewhere and update Documents
SerialConsole.print(F("WARNING - Disabled external WDT reset pin - runCount="));
SerialConsole.println(sh3dNodeConfig.getRunCount());
wii5Controller.tempDisableWDT = true;
break;
case '*':
wii5Display.dumpPins();
break;
// Status etc
case '.':
wii5Controller.setDefaultMode();
break;
case ',':
wii5Display.printMetadata();
break;
case '?':
wii5Controller.statusDump(true);
break;
default:
return false;
break;
}
}
return true;
}
WII5Commands wii5Commands;