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.
This commit is contained in:
+851
@@ -0,0 +1,851 @@
|
||||
// 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 WII5Iridium.cpp
|
||||
* @brief Iridium 9602/9603 SBD modem driver: AT-command state machine.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
WII5Iridium:
|
||||
|
||||
TODO 2024 - Seems fairly stable, check TODO and review code
|
||||
|
||||
TOOO
|
||||
Status
|
||||
Examoe=oles, abny reference= etc.
|
||||
Foundby=xm ... Daee
|
||||
|
||||
How to structure a message:
|
||||
|
||||
* Adding up size of Structs - if < 340 (Iridium Size)
|
||||
WII5_IRIDIUM_BIN_MAX
|
||||
Then just build it up into that binary entry
|
||||
* If larger....
|
||||
NFI
|
||||
* Receive - assume one - and goes into bin buffer then processed
|
||||
* Where is it proessed
|
||||
|
||||
Code Source:
|
||||
|
||||
* WII2_Board/WII2_WaveSim/WII2_WaveSim.ino
|
||||
* NA
|
||||
* WII2_Board/WII2_WaveBuoy/WII2_WaveBuoy.ino
|
||||
* IridiumSBD Library
|
||||
#include <IridiumSBD.h>
|
||||
IridiumSBD isbd(SerialIridium); // , onPin);
|
||||
* WII2_Board/Iridium/
|
||||
* NA
|
||||
|
||||
* States/Iridium_Library
|
||||
* NA
|
||||
* Tracker/IridumData/IridiumData.ino
|
||||
* IridiumSBD Library
|
||||
* WII2_Board/Iridium
|
||||
* NA
|
||||
|
||||
= What do we want to do =
|
||||
|
||||
== Automatic processing ==
|
||||
|
||||
* loop()
|
||||
* Processes any mode it is in, including off
|
||||
*
|
||||
|
||||
== Manual Helpers ==
|
||||
|
||||
* bool off()
|
||||
* Returns true if able to switch off and turns to off mode.
|
||||
* Returns false, if busy and unable to change mode
|
||||
* bool status()
|
||||
* Start status if you can. Will change to off when complete, see lastStatus
|
||||
* Read lastStatus
|
||||
* bool sendSimple(Messaage)
|
||||
* Send a simple message, text or binary
|
||||
* Returns true to say it is prepared
|
||||
* bool sendStart(); - Setup to send messages - only if not already there
|
||||
* uint8_t sendStatus(); - Return status so you can send a message
|
||||
* bool sendMessage(Message); - Return true if buffered and trying, false if not sendStart, or sendStatus is busy
|
||||
* bool sendEnd(); - End send - return true if we can. Will turn off automatically.
|
||||
|
||||
== Examples ==
|
||||
|
||||
* setup()
|
||||
* loop()
|
||||
iridum.loop();
|
||||
|
||||
Want to get the updated status
|
||||
|
||||
// If older than 5 minutes
|
||||
if (lastStatusMillis > 300000)
|
||||
.status()
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <WII5Iridium.h>
|
||||
#include <WII5Sh3dConsole.h>
|
||||
#include <MemoryFree.h>
|
||||
|
||||
#ifdef WII5_COMMS_IRIDIUM
|
||||
void WII5Iridium::begin() {
|
||||
SerialComms.begin(SerialComms_Baud);
|
||||
#ifdef WII5_BUFFER_IRIDIUM
|
||||
setBuffer(wii5BufferIridium, WII5_BUFFER_IRIDIUM);
|
||||
#else
|
||||
console.log(LOG_ERROR, F("Iridium: Error, not setting buffer"));
|
||||
#endif
|
||||
powerSetPin(POWER_COMMS_PIN, POWER_COMMS_ON);
|
||||
powerOff(true); // Forced off at boot
|
||||
step = WII5IRIDIUM_OFF;
|
||||
running = false;
|
||||
initialized = false;
|
||||
imei[0] = '\0';
|
||||
sigQualRetry = 0;
|
||||
sigQualMin = 2;
|
||||
}
|
||||
|
||||
void WII5Iridium::start(bool force) {
|
||||
if (debug)
|
||||
console.log(LOG_DEBUG, F("IRIDIUM: start current=%d"), step);
|
||||
if (step == WII5IRIDIUM_OFF) {
|
||||
recordCount = 0; sendCount = 0;
|
||||
step = WII5IRIDIUM_POWER; stepWait = 0;
|
||||
}
|
||||
powerOn();
|
||||
}
|
||||
|
||||
void WII5Iridium::stop(bool force) {
|
||||
if (debug)
|
||||
console.log(LOG_DEBUG, F("IRIDIUM: stop current=%d"), step);
|
||||
if (step != WII5IRIDIUM_OFF) {
|
||||
// Delays - request off, that sort of thing... ! YES ! TODO
|
||||
step = WII5IRIDIUM_OFF; stepWait = 0;
|
||||
}
|
||||
powerOff(force);
|
||||
}
|
||||
|
||||
bool WII5Iridium::isRunning() {
|
||||
return running;
|
||||
}
|
||||
|
||||
// on
|
||||
void WII5Iridium::powerOn(bool force) {
|
||||
if (!running || force) {
|
||||
if (debug)
|
||||
console.log(LOG_DEBUG, F("IRIDIUM: power ON"));
|
||||
running = true;
|
||||
wii5Controller.shared5On();
|
||||
WII5Power::powerOn();
|
||||
SerialComms.begin(SerialComms_Baud);
|
||||
stream = &SerialComms;
|
||||
beginSerialManager();
|
||||
}
|
||||
}
|
||||
|
||||
// off
|
||||
void WII5Iridium::powerOff(bool force) {
|
||||
if (running || force) {
|
||||
if (debug)
|
||||
console.log(LOG_DEBUG, F("IRIDIUM: power off"));
|
||||
running = false;
|
||||
SerialComms.end();
|
||||
stream = NULL;
|
||||
WII5Power::powerOff();
|
||||
endSerialManager();
|
||||
wii5Controller.shared5Off();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void WII5Iridium::loop() {
|
||||
WII5SerialManager::loop();
|
||||
|
||||
bool first = (step != stepLast);
|
||||
stepLast = step;
|
||||
|
||||
switch (step) {
|
||||
// WII5Iridium_OFF - Completely off, powered down, disabled.
|
||||
case WII5IRIDIUM_OFF:
|
||||
if (first) {
|
||||
currentType = WII5IRIDIUM_REQUEST_NONE;
|
||||
initialized = false;
|
||||
wii5Display.atCommsSend(F("status"), F("off"));
|
||||
powerOff();
|
||||
|
||||
/*
|
||||
if (strlen(imei[0]) == 0) {
|
||||
// TODO No IMEI - Turn on Iridium to get
|
||||
// TODO Don't continue to do this. If done - stop, even if we dont' have one
|
||||
requestFirmware();
|
||||
}
|
||||
*/
|
||||
}
|
||||
break;
|
||||
|
||||
case WII5IRIDIUM_POWER:
|
||||
initialized = false;
|
||||
powerOn();
|
||||
// Wait half a second then spin on
|
||||
if (stepWait > 1000) {
|
||||
step = WII5IRIDIUM_ALIVE; stepWait = 0;
|
||||
if (debug)
|
||||
console.log(LOG_DEBUG, F("step power->alive"));
|
||||
}
|
||||
break;
|
||||
|
||||
case WII5IRIDIUM_ALIVE:
|
||||
initialized = false;
|
||||
sendLine(0);
|
||||
// This probably needs to be _AT (not yet written)
|
||||
processMode = WII5SERIALPARSER_OKHUH;
|
||||
// Boot up config
|
||||
last = WII5SERIALLAST_NONE; sendCount = 0;
|
||||
step = WII5IRIDIUM_BOOT; stepWait = 0;
|
||||
if (debug)
|
||||
console.log(LOG_DEBUG, F("step boot_stop->boot_wait"));
|
||||
break;
|
||||
|
||||
// Boot up config
|
||||
case WII5IRIDIUM_BOOT:
|
||||
if (first) {
|
||||
programCount = 0; programTotal = 3;
|
||||
setTimeout(15000);
|
||||
}
|
||||
switch (sendAll()) {
|
||||
// Still waiting
|
||||
case WII5SERIALCMD_WAITING:
|
||||
break;
|
||||
// Error
|
||||
case WII5SERIALCMD_TIMEOUT:
|
||||
console.log(LOG_ERROR, F("SERIAL: TIMEOUT sending (sendAll:0-3): %s"), buffer);
|
||||
case WII5SERIALCMD_ERROR:
|
||||
console.log(LOG_ERROR, F("SERIAL: ERROR sending (sendAll:0-3): %s"), buffer);
|
||||
|
||||
// TODO Do a retry count here, and possible power cycle
|
||||
|
||||
// Success
|
||||
case WII5SERIALCMD_OK:
|
||||
default:
|
||||
// TODO - Consider starting again with OFF, then step back to READY etc etc
|
||||
step = WII5IRIDIUM_FIRMWARE; stepWait = 0;
|
||||
if (debug)
|
||||
console.log(LOG_DEBUG, F("step program_base->program_start"));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
// Firmware
|
||||
case WII5IRIDIUM_FIRMWARE:
|
||||
if (first) {
|
||||
sendCount = 0;
|
||||
}
|
||||
else if (stepWait > 500) {
|
||||
// TODO This is because we have shared buffer. FFS
|
||||
// TODO also... this could blat half read in data ?
|
||||
if (sendCount == 0) {
|
||||
programLine(4);
|
||||
setTimeout(15000);
|
||||
}
|
||||
switch (sendAndWait(WII5SERIALLAST_BOOTVERSION)) {
|
||||
// Still waiting
|
||||
case WII5SERIALCMD_WAITING:
|
||||
break;
|
||||
|
||||
// Move on
|
||||
case WII5SERIALCMD_TIMEOUT:
|
||||
console.log(LOG_ERROR, F("SERIAL: TIMEOUT sending (programLine:4): %s"), buffer);
|
||||
case WII5SERIALCMD_ERROR:
|
||||
console.log(LOG_ERROR, F("SERIAL: ERROR sending (programLine:4): %s"), buffer);
|
||||
case WII5SERIALCMD_OK:
|
||||
default:
|
||||
// TODO How to keep the return?
|
||||
step = WII5IRIDIUM_IMEI; stepWait = 0;
|
||||
if (debug) console.log(LOG_DEBUG, F("step firmware->signalquality"));
|
||||
break;
|
||||
};
|
||||
}
|
||||
break;
|
||||
|
||||
// IMEI
|
||||
case WII5IRIDIUM_IMEI:
|
||||
if (first) {
|
||||
sendCount = 0;
|
||||
}
|
||||
else if (stepWait > 500) {
|
||||
// TODO This is because we have shared buffer. FFS
|
||||
if (sendCount == 0) {
|
||||
programLine(5);
|
||||
setTimeout(15000);
|
||||
}
|
||||
switch (sendAndWait(WII5SERIALLAST_NUMBER)) {
|
||||
// Still waiting
|
||||
case WII5SERIALCMD_WAITING:
|
||||
break;
|
||||
|
||||
// Move on
|
||||
case WII5SERIALCMD_TIMEOUT:
|
||||
console.log(LOG_ERROR, F("SERIAL: TIMEOUT sending (programLine:5): %s"), buffer);
|
||||
step = WII5IRIDIUM_SIGNALQUALITY; stepWait = 0;
|
||||
break;
|
||||
case WII5SERIALCMD_ERROR:
|
||||
console.log(LOG_ERROR, F("SERIAL: ERROR sending (programLine:5): %s"), buffer);
|
||||
step = WII5IRIDIUM_SIGNALQUALITY; stepWait = 0;
|
||||
break;
|
||||
case WII5SERIALCMD_OK:
|
||||
default:
|
||||
// TODO Woooh.... should be checking length etc.
|
||||
strcpy(imei, buffer);
|
||||
wii5Display.atCommsSend(F("info"), F("imei=%s"), imei);
|
||||
step = WII5IRIDIUM_SIGNALQUALITY; stepWait = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// SYSTEMTIME
|
||||
// case WII5IRIDIUM_SYSTEMTIME:
|
||||
|
||||
case WII5IRIDIUM_SIGNALQUALITY_WAIT:
|
||||
if (first) {
|
||||
if (debug)
|
||||
console.log(LOG_ERROR, F("Irigin: Waiting n seconds before retry signal quality"));
|
||||
}
|
||||
// 15 second delay to retry Signal Quality
|
||||
// TODO for now 5 seconds, alo... should be able check this
|
||||
// TODO 2024 - Making this 20 seconds
|
||||
else if (stepWait > 20000) {
|
||||
if (debug)
|
||||
console.log(LOG_ERROR, F("Irigin: Waiting complete"));
|
||||
step = WII5IRIDIUM_SIGNALQUALITY; stepWait = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
// Signal Quality
|
||||
case WII5IRIDIUM_SIGNALQUALITY:
|
||||
if (first) {
|
||||
sendCount = 0;
|
||||
}
|
||||
else if (stepWait > 500) {
|
||||
// TODO This is because we have shared buffer. FFS
|
||||
if (sendCount == 0) {
|
||||
programLine(7);
|
||||
setTimeout(30000);
|
||||
}
|
||||
switch (sendAndWait(WII5SERIALLAST_ATCSQ)) {
|
||||
// Still waiting
|
||||
case WII5SERIALCMD_WAITING:
|
||||
break;
|
||||
// Move on
|
||||
case WII5SERIALCMD_TIMEOUT:
|
||||
console.log(LOG_ERROR, F("SERIAL: TIMEOUT sending (programLine:7): %s"), buffer);
|
||||
case WII5SERIALCMD_ERROR:
|
||||
console.log(LOG_ERROR, F("SERIAL: ERROR sending (programLine:7): %s"), buffer);
|
||||
case WII5SERIALCMD_OK:
|
||||
default:
|
||||
// TODO Keep this data lastCSQ
|
||||
if (lastVal < sigQualMin) {
|
||||
if (sigQualRetry < IRIDIUM_RETRY_MAX) {
|
||||
sigQualRetry++;
|
||||
wii5Display.atCommsSend(F("info"), F("signalquality=%d,retry=%d"), int(lastVal), int(sigQualRetry));
|
||||
// Setting sendCount to zero, will trigger sending Line 7 again
|
||||
// (not necessary now using signal quality wait) sendCount = 0;
|
||||
step = WII5IRIDIUM_SIGNALQUALITY_WAIT; stepWait = 0;
|
||||
}
|
||||
else {
|
||||
wii5Display.atCommsSend(F("info"), F("signalquality=%d,retry max"), int(lastVal));
|
||||
lastSince = 0;
|
||||
lastSignalQuality = int(lastVal);
|
||||
step = WII5IRIDIUM_SEND_JUMP; stepWait = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
lastSince = 0;
|
||||
lastSignalQuality = lastVal;
|
||||
wii5Display.atCommsSend(F("info"), F("signalquality=%d"), int(lastSignalQuality));
|
||||
step = WII5IRIDIUM_SEND_JUMP; stepWait = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (stepWait > 120000) {
|
||||
lastSince = 0;
|
||||
lastSignalQuality = 0;
|
||||
wii5Display.atCommsSend(F("info"), F("signalquality=0,timeout"));
|
||||
step = WII5IRIDIUM_SEND_JUMP; stepWait = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
// Wait here for a retry.
|
||||
case WII5IRIDIUM_RETRY:
|
||||
if (first) {
|
||||
if (debug)
|
||||
console.log(LOG_ERROR, F("Irigin: Waiting n seconds before retry send"));
|
||||
}
|
||||
// 15 second delay to retry Signal Quality
|
||||
else if (stepWait > 20000) {
|
||||
step = WII5IRIDIUM_SEND_JUMP; stepWait = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
// Choose - send Text or Binary - always returns data
|
||||
case WII5IRIDIUM_SEND_JUMP:
|
||||
initialized = true;
|
||||
if (currentType == WII5IRIDIUM_REQUEST_SIGNALQUALITY) {
|
||||
// TODO - should be done
|
||||
step = WII5IRIDIUM_WAITING; stepWait = 0;
|
||||
}
|
||||
else if (currentType == WII5IRIDIUM_REQUEST_TIME) {
|
||||
// TODO - should be done
|
||||
step = WII5IRIDIUM_WAITING; stepWait = 0;
|
||||
}
|
||||
else if (currentType == WII5IRIDIUM_REQUEST_FIRMWARE) {
|
||||
// TODO - should be done
|
||||
step = WII5IRIDIUM_WAITING; stepWait = 0;
|
||||
}
|
||||
else if (currentType == WII5IRIDIUM_REQUEST_SENDTEXT) {
|
||||
step = WII5IRIDIUM_PREPARE_TEXT; stepWait = 0;
|
||||
if (debug)
|
||||
console.log(LOG_DEBUG, F("step send_jump->prepare_text"));
|
||||
}
|
||||
else if (currentType == WII5IRIDIUM_REQUEST_SENDBIN) {
|
||||
step = WII5IRIDIUM_PREPARE_BIN1; stepWait = 0;
|
||||
if (debug)
|
||||
console.log(LOG_DEBUG, F("step send_jump->prepare_bin1"));
|
||||
}
|
||||
else {
|
||||
step = WII5IRIDIUM_OFF; stepWait = 0;
|
||||
if (debug)
|
||||
console.log(LOG_DEBUG, F("step send_jump->off"));
|
||||
}
|
||||
break;
|
||||
|
||||
// Send Text
|
||||
case WII5IRIDIUM_PREPARE_TEXT:
|
||||
if (first) {
|
||||
if (debug) console.log(LOG_DEBUG, F("Iridium: Setting PrepareText Sentence"));
|
||||
wii5Display.atCommsSend(F("send"), F("prepare=text,length=%d"), int(strlen(wii5BinaryIridium)));
|
||||
sendCount = 0;
|
||||
}
|
||||
else if (stepWait > 500) {
|
||||
|
||||
//
|
||||
// AT+SBDWT=hello - Text send, maxium length = 120 bytes
|
||||
//
|
||||
|
||||
if (sendCount == 0) {
|
||||
// strncpy_P(buffer ,(PGM_P) F("AT+SBDWT=My first nonBlocking Iridium attempt"), bufMax);
|
||||
// TODO will this be big enough
|
||||
sprintf_P(buffer, PSTR("AT+SBDWT=%s"), wii5BinaryIridium);
|
||||
setTimeout(15000);
|
||||
}
|
||||
switch (sendAndWait()) {
|
||||
// Still waiting
|
||||
case WII5SERIALCMD_WAITING:
|
||||
break;
|
||||
|
||||
// Move on
|
||||
case WII5SERIALCMD_TIMEOUT:
|
||||
console.log(LOG_ERROR, F("SERIAL: TIMEOUT sending (AT+SBDWT=X): %s"), buffer);
|
||||
case WII5SERIALCMD_ERROR:
|
||||
console.log(LOG_ERROR, F("SERIAL: ERROR sending (AT+SBDWT=X): %s"), buffer);
|
||||
case WII5SERIALCMD_OK:
|
||||
default:
|
||||
if (debug)
|
||||
console.log(LOG_DEBUG, F("SERIAL: OK setting up (AT+SBDWT=X)"));
|
||||
step = WII5IRIDIUM_SEND; stepWait = 0;
|
||||
if (debug) console.log(LOG_DEBUG, F("step prepare_text->send_text"));
|
||||
break;
|
||||
};
|
||||
}
|
||||
break;
|
||||
|
||||
case WII5IRIDIUM_RECEIVE:
|
||||
if (first) {
|
||||
if (debug) console.log(LOG_DEBUG, F("Iridium: Receiving Data"));
|
||||
sendCount = 0;
|
||||
// Use the shared Binary buffer for incoming now
|
||||
memset(wii5BinaryIridium, 0, 340);
|
||||
binBuffer = wii5BinaryIridium;
|
||||
processMode = WII5SERIALPARSER_BINARY1;
|
||||
binBufferExpect = 0; // Important - must set to 0
|
||||
// SEND THIS - AT+SBDRB
|
||||
strncpy_P(buffer ,(PGM_P) F("AT+SBDRB"), bufMax);
|
||||
stream->print(buffer);
|
||||
sendNewLine();
|
||||
wii5Display.atCommsSend(F("receive"), F("start"));
|
||||
}
|
||||
else if (stepWait > 500) {
|
||||
if (processMode != WII5SERIALPARSER_BINARY1) {
|
||||
// OK So we have a message !
|
||||
// Put it somewhere
|
||||
|
||||
// Swith process Mode back and move on
|
||||
// - We can send here, no delay, then switch to command wait
|
||||
// - Command wait will be looking for reply in Command TODO
|
||||
// - or Timeout
|
||||
// - At which point it will send a reply, and receive next command
|
||||
// - On receiveing command can be go three ways.
|
||||
// . Didn't understand the command - ignore / log locally
|
||||
// . Understood - got a reply, and send a replly
|
||||
// . Undertsood but timeout... send reply timeout
|
||||
lastReceive = WII5IRIDIUMRECEIVERESULT_OK;
|
||||
lastReceiveLen = binBufferExpect;
|
||||
lastReceiveBuff = wii5BinaryIridium[0]; // First 2 are length;
|
||||
wii5BinaryIridium[lastReceiveLen] = '\0';
|
||||
// TODO Should we strip last 2 to zero?
|
||||
|
||||
// TODO - What if the queue says there is more to receive. Maybe just wait
|
||||
// since we are alwqys sending lots, and receiving little ?
|
||||
processMode = WII5SERIALPARSER_OKHUH;
|
||||
wii5Display.atCommsSend(F("receive"), F("complete,size=%d"), lastReceiveLen);
|
||||
step = WII5IRIDIUM_WAITING; stepWait = 0;
|
||||
}
|
||||
}
|
||||
else if (stepWait > 5000) {
|
||||
wii5Display.atCommsSend(F("receive"), F("timeout"));
|
||||
// TODO Timeout... Force back clear etc (how to clear buffers etc
|
||||
// TODO Show errors
|
||||
processMode = WII5SERIALPARSER_OKHUH;
|
||||
step = WII5IRIDIUM_WAITING; stepWait = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case WII5IRIDIUM_SEND:
|
||||
if (first) {
|
||||
if (debug) console.log(LOG_DEBUG, F("Iridium: Setting SendToSat Sentence"));
|
||||
sendCount = 0;
|
||||
}
|
||||
else if (stepWait > 500) {
|
||||
if (sendCount == 0) {
|
||||
strncpy_P(buffer ,(PGM_P) F("AT+SBDI"), bufMax);
|
||||
setTimeout(45000);
|
||||
}
|
||||
switch (sendAndWait(WII5SERIALLAST_ATSBDI)) {
|
||||
// Still waiting
|
||||
case WII5SERIALCMD_WAITING:
|
||||
break;
|
||||
|
||||
// Move on
|
||||
case WII5SERIALCMD_TIMEOUT:
|
||||
console.log(LOG_ERROR, F("SERIAL: TIMEOUT sending (AT+SBDI): %s"), buffer);
|
||||
case WII5SERIALCMD_ERROR:
|
||||
console.log(LOG_ERROR, F("SERIAL: ERROR sending (AT+SBDI): %s"), buffer);
|
||||
wii5Display.atCommsSend(F("send"), F("failed,during +SBDI"));
|
||||
lastSend = WII5IRIDIUMSENDRESULT_FAILED_OTHER;
|
||||
step = WII5IRIDIUM_WAITING; stepWait = 0;
|
||||
currentType = WII5IRIDIUM_REQUEST_NONE;
|
||||
break;
|
||||
|
||||
case WII5SERIALCMD_OK:
|
||||
default:
|
||||
// TODO CHeck for return value of +SBDI or +SBDIX incase we need to retry
|
||||
wii5Display.atCommsSend(F("send"), F("success,mo_status=%lu,mo_MSN=%lu,mt_status=%lu,mt_MSN=%lu,mt_len=%lu,mt_queued=%lu"),
|
||||
recordVals[0], recordVals[1],
|
||||
recordVals[2], recordVals[3], recordVals[4], recordVals[5]
|
||||
);
|
||||
lastMOMSN = recordVals[1];
|
||||
lastSince = 0;
|
||||
|
||||
switch(recordVals[0]) {
|
||||
|
||||
// Success fully sent or nothing to send
|
||||
case 0:
|
||||
case 1:
|
||||
// LOG SUCCESS !!!
|
||||
console.log(LOG_INFO, F("Iridium: SEND: Success"));
|
||||
lastSend = WII5IRIDIUMSENDRESULT_OK;
|
||||
currentType = WII5IRIDIUM_REQUEST_NONE;
|
||||
|
||||
// Do we have a waiting message, download it off the Iridium
|
||||
// 2 = Number of messages, 4 = Length of this one
|
||||
if ( (recordVals[2] > 0) && (recordVals[4] > 0) ) {
|
||||
wii5Display.atCommsSend(F("receive"), F("mt_len=%lu"),
|
||||
recordVals[4]
|
||||
);
|
||||
step = WII5IRIDIUM_RECEIVE; stepWait = 0;
|
||||
if (debug) console.log(LOG_DEBUG, F("step send_text->receive`"));
|
||||
}
|
||||
|
||||
// No waiting messages.
|
||||
else {
|
||||
step = WII5IRIDIUM_WAITING; stepWait = 0;
|
||||
// TODO Include Iridium message ID etc etc
|
||||
wii5Display.atCommsSend(F("send"), F("complete"));
|
||||
// TODO Capture etc
|
||||
if (debug) console.log(LOG_DEBUG, F("step send_text->waiting`"));
|
||||
}
|
||||
break;
|
||||
|
||||
// Other error
|
||||
case 2:
|
||||
default:
|
||||
// Retry
|
||||
retry++;
|
||||
if (retry < IRIDIUM_RETRY_MAX) {
|
||||
// LOG RETRY !!!
|
||||
wii5Display.atCommsSend(F("send"), F("failed,retry=%d"), int(retry));
|
||||
step = WII5IRIDIUM_RETRY; stepWait = 0;
|
||||
}
|
||||
else {
|
||||
// LOG FAILED !!!
|
||||
wii5Display.atCommsSend(F("send"), F("failed,exit"));
|
||||
lastSend = WII5IRIDIUMSENDRESULT_FAILED_OTHER;
|
||||
step = WII5IRIDIUM_WAITING; stepWait = 0;
|
||||
currentType = WII5IRIDIUM_REQUEST_NONE;
|
||||
}
|
||||
break;
|
||||
};
|
||||
|
||||
// TODO - check for receive stuff
|
||||
break;
|
||||
};
|
||||
}
|
||||
break;
|
||||
|
||||
// Send Binary
|
||||
case WII5IRIDIUM_PREPARE_BIN1:
|
||||
//
|
||||
// +SBDWB=<SBD message length>
|
||||
//
|
||||
// {binary SBD message} + {2-byte checksum}
|
||||
//
|
||||
// The checksum is the least signi cant 2-bytes of the summation of the entire SBD message. The high order byte will be sent rst. For example if the 9602 were to send the word “hello” encoded in ASCII to the DTE the binary stream would be hex 00 05 68 65 6c 6c 6f 02 14.
|
||||
//
|
||||
// Response:
|
||||
// 0 SBD message successfully written to the 9602.
|
||||
// 1 SBD message write timeout. An insu cient number of bytes were transferred to 9602 during the transfer period of 60 seconds.
|
||||
// 2 SBD message checksum sent from DTE does not match the checksum calculated by the 9602.
|
||||
// 3 SBD message size is not correct. The maximum mobile originated SBD message length is 340 bytes. The minimum mobile originated SBD message length is 1 byte.
|
||||
//
|
||||
if (first) {
|
||||
if (debug) console.log(LOG_DEBUG, F("Iridium: Setting PrepareBin Sentence"));
|
||||
wii5Display.atCommsSend(F("send"), F("prepare=binary,length=%d"), int(binSize));
|
||||
sendCount = 0;
|
||||
}
|
||||
else if (stepWait > 500) {
|
||||
|
||||
//
|
||||
// AT+SBDWB=bytes
|
||||
//
|
||||
|
||||
if (sendCount == 0) {
|
||||
sprintf_P(buffer, PSTR("AT+SBDWB=%d"), int(binSize));
|
||||
setTimeout(15000);
|
||||
}
|
||||
switch (sendAndWait(WII5SERIALLAST_READY)) {
|
||||
case WII5SERIALCMD_WAITING:
|
||||
break;
|
||||
case WII5SERIALCMD_TIMEOUT:
|
||||
console.log(LOG_ERROR, F("SERIAL: TIMEOUT sending (AT+SBDWB=X): %s"), buffer);
|
||||
case WII5SERIALCMD_ERROR:
|
||||
console.log(LOG_ERROR, F("SERIAL: ERROR sending (AT+SBDWB=X): %s"), buffer);
|
||||
case WII5SERIALCMD_OK:
|
||||
default:
|
||||
if (debug)
|
||||
console.log(LOG_INFO, F("SERIAL: OK setting up (AT+SBDWB=X)"));
|
||||
step = WII5IRIDIUM_PREPARE_BIN2; stepWait = 0;
|
||||
if (debug) console.log(LOG_DEBUG, F("step prepare_text->prepare_bin2"));
|
||||
break;
|
||||
};
|
||||
}
|
||||
break;
|
||||
|
||||
case WII5IRIDIUM_PREPARE_BIN2:
|
||||
if (first) {
|
||||
// Logging?
|
||||
}
|
||||
else if (stepWait > 500) {
|
||||
checksum = 0;
|
||||
if (passthrough)
|
||||
console.printBinary(wii5BinaryIridium, binSize);
|
||||
for (loopcount = 0; loopcount < binSize; loopcount++) {
|
||||
stream->write(wii5BinaryIridium[loopcount]);
|
||||
checksum += (uint8_t)wii5BinaryIridium[loopcount];
|
||||
}
|
||||
stream->write(checksum >> 8);
|
||||
stream->write(checksum & 0xFF);
|
||||
|
||||
// TODO how to find Status
|
||||
// 0 success
|
||||
// 1 TIMEOUT
|
||||
// 2 checksum errors
|
||||
// 3 size errors
|
||||
|
||||
step = WII5IRIDIUM_SEND; stepWait = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
// Complete
|
||||
case WII5IRIDIUM_STOP_PREPARE:
|
||||
break;
|
||||
|
||||
case WII5IRIDIUM_END:
|
||||
break;
|
||||
|
||||
// Wait here... just in case Maths wants to do some more. Give them 1 min
|
||||
case WII5IRIDIUM_WAITING:
|
||||
// TODO Configure time etc (should we send reminder?)
|
||||
if (first) {
|
||||
wii5Display.atCommsSend(F("status"), F("waiting"));
|
||||
}
|
||||
if (stepWait > 60000) {
|
||||
step = WII5IRIDIUM_OFF; stepWait = 0;
|
||||
currentType = WII5IRIDIUM_REQUEST_NONE;
|
||||
if (debug) console.log(LOG_DEBUG, F("step waiting->off`"));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
console.log(LOG_FATAL, F("IRIDIUM: Default step... step=%d"), step);
|
||||
step = WII5IRIDIUM_OFF;
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Manually set the binary data - note, we have no buffer, so must have external for hhis
|
||||
void WII5Iridium::setBinary(uint8_t *buf, uint16_t size) {
|
||||
// Memcopy data size or max iridium size
|
||||
binSize = size <= WII5_IRIDIUM_BIN_MAX ? size : WII5_IRIDIUM_BIN_MAX;
|
||||
memcpy(wii5BinaryIridium, buf, binSize);
|
||||
}
|
||||
|
||||
void WII5Iridium::setBinSize(uint16_t size) {
|
||||
binSize = size <= WII5_IRIDIUM_BIN_MAX ? size : WII5_IRIDIUM_BIN_MAX;
|
||||
}
|
||||
|
||||
void WII5Iridium::setText(char *str) {
|
||||
strncpy(wii5BinaryIridium, *(char *)str, WII5_IRIDIUM_BIN_MAX); // WII5_STORAGE_FILENAME_LEN);
|
||||
}
|
||||
// Allow fprintf params like console etc.
|
||||
void WII5Iridium::setText(const __FlashStringHelper *str) {
|
||||
strncpy_P(wii5BinaryIridium, (const char *)str, WII5_IRIDIUM_BIN_MAX);
|
||||
}
|
||||
|
||||
// Get current
|
||||
WII5IRIDIUM_REQUEST WII5Iridium::currentRequest() {
|
||||
return currentType;
|
||||
}
|
||||
|
||||
bool WII5Iridium::requestSendText() {
|
||||
// If no text, faile - return false,
|
||||
currentType = WII5IRIDIUM_REQUEST_SENDTEXT;
|
||||
recordCount = 0; sendCount = 0; stepWait = 0;
|
||||
lastSend = WII5IRIDIUMSENDRESULT_NONE;
|
||||
lastReceive = WII5IRIDIUMRECEIVERESULT_NONE;
|
||||
retry = 0;
|
||||
sigQualRetry = 0;
|
||||
if (initialized)
|
||||
step = WII5IRIDIUM_SEND_JUMP;
|
||||
else
|
||||
step = WII5IRIDIUM_POWER;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WII5Iridium::requestSendBinary() {
|
||||
// If we have binary data.... else return false
|
||||
currentType = WII5IRIDIUM_REQUEST_SENDBIN;
|
||||
lastSend = WII5IRIDIUMSENDRESULT_NONE;
|
||||
lastReceive = WII5IRIDIUMRECEIVERESULT_NONE;
|
||||
recordCount = 0; sendCount = 0; stepWait = 0;
|
||||
retry = 0;
|
||||
sigQualRetry = 0;
|
||||
if (initialized)
|
||||
step = WII5IRIDIUM_SEND_JUMP;
|
||||
else
|
||||
step = WII5IRIDIUM_POWER;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WII5Iridium::requestFirmware() {
|
||||
currentType = WII5IRIDIUM_REQUEST_FIRMWARE;
|
||||
lastSend = WII5IRIDIUMSENDRESULT_NONE;
|
||||
lastReceive = WII5IRIDIUMRECEIVERESULT_NONE;
|
||||
recordCount = 0; sendCount = 0; stepWait = 0;
|
||||
step = WII5IRIDIUM_POWER;
|
||||
retry = 0;
|
||||
sigQualRetry = 0;
|
||||
}
|
||||
|
||||
|
||||
// Waiting - Feel free to check the last status and send another
|
||||
bool WII5Iridium::waiting() {
|
||||
return ((step == WII5IRIDIUM_OFF) || (step == WII5IRIDIUM_WAITING));
|
||||
}
|
||||
|
||||
/*
|
||||
void WII5Iridium::clearLast() {
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
void WII5Iridium::programLine(uint16_t l) {
|
||||
// Main Programming
|
||||
switch (l) {
|
||||
// BOOT=0..3,
|
||||
case 0:
|
||||
strncpy_P(buffer ,(PGM_P) F("ATE0"), bufMax);
|
||||
break;
|
||||
case 1:
|
||||
strncpy_P(buffer ,(PGM_P) F("AT&D0"), bufMax);
|
||||
break;
|
||||
case 2:
|
||||
strncpy_P(buffer ,(PGM_P) F("AT&K0"), bufMax);
|
||||
break;
|
||||
case 3:
|
||||
strncpy_P(buffer ,(PGM_P) F("AT+SBDMTA=0"), bufMax);
|
||||
break;
|
||||
|
||||
// Firmware
|
||||
case 4:
|
||||
strncpy_P(buffer ,(PGM_P) F("AT+CGMR"), bufMax);
|
||||
break;
|
||||
|
||||
// IMEI
|
||||
case 5:
|
||||
strncpy_P(buffer ,(PGM_P) F("AT+CGSN"), bufMax);
|
||||
break;
|
||||
|
||||
// System Time
|
||||
case 6:
|
||||
strncpy_P(buffer ,(PGM_P) F("AT-MSSTM"), bufMax);
|
||||
break;
|
||||
|
||||
// Signal Quality
|
||||
case 7:
|
||||
strncpy_P(buffer ,(PGM_P) F("AT+CSQ"), bufMax);
|
||||
break;
|
||||
|
||||
case 8:
|
||||
strncpy_P(buffer ,(PGM_P) F("AT"), bufMax);
|
||||
break;
|
||||
|
||||
// send Text
|
||||
|
||||
// send Binary
|
||||
|
||||
// HOW TO: Retries
|
||||
|
||||
// HOW TO: Work around firmware issues
|
||||
|
||||
default:
|
||||
console.log(LOG_FATAL, F("IRIDIUM: request invalid programming string"));
|
||||
buffer[0] = '\0';
|
||||
break;
|
||||
}
|
||||
|
||||
if (debug)
|
||||
console.log(LOG_DEBUG, F("IRIDIUM: set command=%d buffer=%s"), l, buffer);
|
||||
}
|
||||
|
||||
void WII5Iridium::sendNewLine() {
|
||||
stream->print(F("\r"));
|
||||
}
|
||||
|
||||
WII5Iridium wii5Iridium;
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user