Just start a new PR. Conflicts were too wild

This commit is contained in:
Ben Meadors 2023-01-22 08:48:31 -06:00
parent fc5e80a5cc
commit 4c9f0b2646
5 changed files with 238 additions and 186 deletions

View File

@ -2,8 +2,9 @@
// See http://go.microsoft.com/fwlink/?LinkId=827846 // See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format // for the documentation about the extensions.json format
"recommendations": [ "recommendations": [
"ms-vscode.cpptools", "platformio.platformio-ide"
"platformio.platformio-ide",
"trunk.io"
], ],
"unwantedRecommendations": [
"ms-vscode.cpptools-extension-pack"
]
} }

View File

@ -29,7 +29,8 @@ PhoneAPI::~PhoneAPI()
void PhoneAPI::handleStartConfig() void PhoneAPI::handleStartConfig()
{ {
// Must be before setting state (because state is how we know !connected) // Must be before setting state (because state is how we know !connected)
if (!isConnected()) { if (!isConnected())
{
onConnectionChanged(true); onConnectionChanged(true);
observe(&service.fromNumChanged); observe(&service.fromNumChanged);
observe(&xModem.packetReady); observe(&xModem.packetReady);
@ -46,7 +47,8 @@ void PhoneAPI::handleStartConfig()
void PhoneAPI::close() void PhoneAPI::close()
{ {
if (state != STATE_SEND_NOTHING) { if (state != STATE_SEND_NOTHING)
{
state = STATE_SEND_NOTHING; state = STATE_SEND_NOTHING;
unobserve(&service.fromNumChanged); unobserve(&service.fromNumChanged);
@ -60,9 +62,11 @@ void PhoneAPI::close()
void PhoneAPI::checkConnectionTimeout() void PhoneAPI::checkConnectionTimeout()
{ {
if (isConnected()) { if (isConnected())
{
bool newContact = checkIsConnected(); bool newContact = checkIsConnected();
if (!newContact) { if (!newContact)
{
LOG_INFO("Lost phone connection\n"); LOG_INFO("Lost phone connection\n");
close(); close();
} }
@ -80,8 +84,10 @@ bool PhoneAPI::handleToRadio(const uint8_t *buf, size_t bufLength)
// return (lastContactMsec != 0) && // return (lastContactMsec != 0) &&
memset(&toRadioScratch, 0, sizeof(toRadioScratch)); memset(&toRadioScratch, 0, sizeof(toRadioScratch));
if (pb_decode_from_bytes(buf, bufLength, &meshtastic_ToRadio_msg, &toRadioScratch)) { if (pb_decode_from_bytes(buf, bufLength, &meshtastic_ToRadio_msg, &toRadioScratch))
switch (toRadioScratch.which_payload_variant) { {
switch (toRadioScratch.which_payload_variant)
{
case meshtastic_ToRadio_packet_tag: case meshtastic_ToRadio_packet_tag:
return handleToRadioPacket(toRadioScratch.packet); return handleToRadioPacket(toRadioScratch.packet);
case meshtastic_ToRadio_want_config_id_tag: case meshtastic_ToRadio_want_config_id_tag:
@ -102,7 +108,9 @@ bool PhoneAPI::handleToRadio(const uint8_t *buf, size_t bufLength)
// LOG_DEBUG("Error: unexpected ToRadio variant\n"); // LOG_DEBUG("Error: unexpected ToRadio variant\n");
break; break;
} }
} else { }
else
{
LOG_ERROR("Error: ignoring malformed toradio\n"); LOG_ERROR("Error: ignoring malformed toradio\n");
} }
@ -125,7 +133,8 @@ bool PhoneAPI::handleToRadio(const uint8_t *buf, size_t bufLength)
*/ */
size_t PhoneAPI::getFromRadio(uint8_t *buf) size_t PhoneAPI::getFromRadio(uint8_t *buf)
{ {
if (!available()) { if (!available())
{
// LOG_DEBUG("getFromRadio=not available\n"); // LOG_DEBUG("getFromRadio=not available\n");
return 0; return 0;
} }
@ -133,7 +142,8 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
memset(&fromRadioScratch, 0, sizeof(fromRadioScratch)); memset(&fromRadioScratch, 0, sizeof(fromRadioScratch));
// Advance states as needed // Advance states as needed
switch (state) { switch (state)
{
case STATE_SEND_NOTHING: case STATE_SEND_NOTHING:
LOG_INFO("getFromRadio=STATE_SEND_NOTHING\n"); LOG_INFO("getFromRadio=STATE_SEND_NOTHING\n");
break; break;
@ -150,18 +160,22 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
service.refreshMyNodeInfo(); // Update my NodeInfo because the client will be asking for it soon. service.refreshMyNodeInfo(); // Update my NodeInfo because the client will be asking for it soon.
break; break;
case STATE_SEND_NODEINFO: { case STATE_SEND_NODEINFO:
{
LOG_INFO("getFromRadio=STATE_SEND_NODEINFO\n"); LOG_INFO("getFromRadio=STATE_SEND_NODEINFO\n");
const meshtastic_NodeInfo *info = nodeInfoForPhone; const meshtastic_NodeInfo *info = nodeInfoForPhone;
nodeInfoForPhone = NULL; // We just consumed a nodeinfo, will need a new one next time nodeInfoForPhone = NULL; // We just consumed a nodeinfo, will need a new one next time
if (info) { if (info)
{
LOG_INFO("Sending nodeinfo: num=0x%x, lastseen=%u, id=%s, name=%s\n", info->num, info->last_heard, info->user.id, LOG_INFO("Sending nodeinfo: num=0x%x, lastseen=%u, id=%s, name=%s\n", info->num, info->last_heard, info->user.id,
info->user.long_name); info->user.long_name);
fromRadioScratch.which_payload_variant = meshtastic_FromRadio_node_info_tag; fromRadioScratch.which_payload_variant = meshtastic_FromRadio_node_info_tag;
fromRadioScratch.node_info = *info; fromRadioScratch.node_info = *info;
// Stay in current state until done sending nodeinfos // Stay in current state until done sending nodeinfos
} else { }
else
{
LOG_INFO("Done sending nodeinfos\n"); LOG_INFO("Done sending nodeinfos\n");
state = STATE_SEND_CHANNELS; state = STATE_SEND_CHANNELS;
// Go ahead and send that ID right now // Go ahead and send that ID right now
@ -176,7 +190,8 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
fromRadioScratch.channel = channels.getByIndex(config_state); fromRadioScratch.channel = channels.getByIndex(config_state);
config_state++; config_state++;
// Advance when we have sent all of our Channels // Advance when we have sent all of our Channels
if (config_state >= MAX_NUM_CHANNELS) { if (config_state >= MAX_NUM_CHANNELS)
{
state = STATE_SEND_CONFIG; state = STATE_SEND_CONFIG;
config_state = _meshtastic_AdminMessage_ConfigType_MIN + 1; config_state = _meshtastic_AdminMessage_ConfigType_MIN + 1;
} }
@ -185,7 +200,8 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
case STATE_SEND_CONFIG: case STATE_SEND_CONFIG:
LOG_INFO("getFromRadio=STATE_SEND_CONFIG\n"); LOG_INFO("getFromRadio=STATE_SEND_CONFIG\n");
fromRadioScratch.which_payload_variant = meshtastic_FromRadio_config_tag; fromRadioScratch.which_payload_variant = meshtastic_FromRadio_config_tag;
switch (config_state) { switch (config_state)
{
case meshtastic_Config_device_tag: case meshtastic_Config_device_tag:
fromRadioScratch.config.which_payload_variant = meshtastic_Config_device_tag; fromRadioScratch.config.which_payload_variant = meshtastic_Config_device_tag;
fromRadioScratch.config.payload_variant.device = config.device; fromRadioScratch.config.payload_variant.device = config.device;
@ -224,7 +240,8 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
config_state++; config_state++;
// Advance when we have sent all of our config objects // Advance when we have sent all of our config objects
if (config_state > (_meshtastic_AdminMessage_ConfigType_MAX + 1)) { if (config_state > (_meshtastic_AdminMessage_ConfigType_MAX + 1))
{
state = STATE_SEND_MODULECONFIG; state = STATE_SEND_MODULECONFIG;
config_state = _meshtastic_AdminMessage_ModuleConfigType_MIN + 1; config_state = _meshtastic_AdminMessage_ModuleConfigType_MIN + 1;
} }
@ -233,7 +250,8 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
case STATE_SEND_MODULECONFIG: case STATE_SEND_MODULECONFIG:
LOG_INFO("getFromRadio=STATE_SEND_MODULECONFIG\n"); LOG_INFO("getFromRadio=STATE_SEND_MODULECONFIG\n");
fromRadioScratch.which_payload_variant = meshtastic_FromRadio_moduleConfig_tag; fromRadioScratch.which_payload_variant = meshtastic_FromRadio_moduleConfig_tag;
switch (config_state) { switch (config_state)
{
case meshtastic_ModuleConfig_mqtt_tag: case meshtastic_ModuleConfig_mqtt_tag:
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_mqtt_tag; fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_mqtt_tag;
fromRadioScratch.moduleConfig.payload_variant.mqtt = moduleConfig.mqtt; fromRadioScratch.moduleConfig.payload_variant.mqtt = moduleConfig.mqtt;
@ -276,7 +294,8 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
config_state++; config_state++;
// Advance when we have sent all of our ModuleConfig objects // Advance when we have sent all of our ModuleConfig objects
if (config_state > (_meshtastic_AdminMessage_ModuleConfigType_MAX + 1)) { if (config_state > (_meshtastic_AdminMessage_ModuleConfigType_MAX + 1))
{
state = STATE_SEND_COMPLETE_ID; state = STATE_SEND_COMPLETE_ID;
config_state = 0; config_state = 0;
} }
@ -293,16 +312,20 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
case STATE_SEND_PACKETS: case STATE_SEND_PACKETS:
// Do we have a message from the mesh? // Do we have a message from the mesh?
LOG_INFO("getFromRadio=STATE_SEND_PACKETS\n"); LOG_INFO("getFromRadio=STATE_SEND_PACKETS\n");
if (queueStatusPacketForPhone) { if (queueStatusPacketForPhone)
{
fromRadioScratch.which_payload_variant = meshtastic_FromRadio_queueStatus_tag; fromRadioScratch.which_payload_variant = meshtastic_FromRadio_queueStatus_tag;
fromRadioScratch.queueStatus = *queueStatusPacketForPhone; fromRadioScratch.queueStatus = *queueStatusPacketForPhone;
releaseQueueStatusPhonePacket(); releaseQueueStatusPhonePacket();
} else if (xmodemPacketForPhone) { }
else if (xmodemPacketForPhone.control != meshtastic_XModem_Control_NUL)
{
fromRadioScratch.which_payload_variant = meshtastic_FromRadio_xmodemPacket_tag; fromRadioScratch.which_payload_variant = meshtastic_FromRadio_xmodemPacket_tag;
fromRadioScratch.xmodemPacket = *xmodemPacketForPhone; fromRadioScratch.xmodemPacket = xmodemPacketForPhone;
free(xmodemPacketForPhone); xmodemPacketForPhone = meshtastic_XModem_init_zero;
xmodemPacketForPhone = NULL; }
} else if (packetForPhone) { else if (packetForPhone)
{
printPacket("phone downloaded packet", packetForPhone); printPacket("phone downloaded packet", packetForPhone);
// Encapsulate as a FromRadio packet // Encapsulate as a FromRadio packet
@ -317,7 +340,8 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
} }
// Do we have a message from the mesh? // Do we have a message from the mesh?
if (fromRadioScratch.which_payload_variant != 0) { if (fromRadioScratch.which_payload_variant != 0)
{
// Encapsulate as a FromRadio packet // Encapsulate as a FromRadio packet
size_t numbytes = pb_encode_to_bytes(buf, meshtastic_FromRadio_size, &meshtastic_FromRadio_msg, &fromRadioScratch); size_t numbytes = pb_encode_to_bytes(buf, meshtastic_FromRadio_size, &meshtastic_FromRadio_msg, &fromRadioScratch);
@ -336,7 +360,8 @@ void PhoneAPI::handleDisconnect()
void PhoneAPI::releasePhonePacket() void PhoneAPI::releasePhonePacket()
{ {
if (packetForPhone) { if (packetForPhone)
{
service.releaseToPool(packetForPhone); // we just copied the bytes, so don't need this buffer anymore service.releaseToPool(packetForPhone); // we just copied the bytes, so don't need this buffer anymore
packetForPhone = NULL; packetForPhone = NULL;
} }
@ -344,7 +369,8 @@ void PhoneAPI::releasePhonePacket()
void PhoneAPI::releaseQueueStatusPhonePacket() void PhoneAPI::releaseQueueStatusPhonePacket()
{ {
if (queueStatusPacketForPhone) { if (queueStatusPacketForPhone)
{
service.releaseQueueStatusToPool(queueStatusPacketForPhone); service.releaseQueueStatusToPool(queueStatusPacketForPhone);
queueStatusPacketForPhone = NULL; queueStatusPacketForPhone = NULL;
} }
@ -355,7 +381,8 @@ void PhoneAPI::releaseQueueStatusPhonePacket()
*/ */
bool PhoneAPI::available() bool PhoneAPI::available()
{ {
switch (state) { switch (state)
{
case STATE_SEND_NOTHING: case STATE_SEND_NOTHING:
return false; return false;
case STATE_SEND_MY_INFO: case STATE_SEND_MY_INFO:
@ -370,14 +397,15 @@ bool PhoneAPI::available()
nodeInfoForPhone = nodeDB.readNextInfo(); nodeInfoForPhone = nodeDB.readNextInfo();
return true; // Always say we have something, because we might need to advance our state machine return true; // Always say we have something, because we might need to advance our state machine
case STATE_SEND_PACKETS: { case STATE_SEND_PACKETS:
{
if (!queueStatusPacketForPhone) if (!queueStatusPacketForPhone)
queueStatusPacketForPhone = service.getQueueStatusForPhone(); queueStatusPacketForPhone = service.getQueueStatusForPhone();
bool hasPacket = !!queueStatusPacketForPhone; bool hasPacket = !!queueStatusPacketForPhone;
if (hasPacket) if (hasPacket)
return true; return true;
if (!xmodemPacketForPhone) if (xmodemPacketForPhone.control != meshtastic_XModem_Control_NUL)
xmodemPacketForPhone = xModem.getForPhone(); xmodemPacketForPhone = xModem.getForPhone();
hasPacket = !!packetForPhone; hasPacket = !!packetForPhone;
if (hasPacket) if (hasPacket)
@ -413,10 +441,12 @@ int PhoneAPI::onNotify(uint32_t newValue)
checkConnectionTimeout(); // a handy place to check if we've heard from the phone (since the BLE version doesn't call this checkConnectionTimeout(); // a handy place to check if we've heard from the phone (since the BLE version doesn't call this
// from idle) // from idle)
if (state == STATE_SEND_PACKETS) { if (state == STATE_SEND_PACKETS)
{
LOG_INFO("Telling client we have new packets %u\n", newValue); LOG_INFO("Telling client we have new packets %u\n", newValue);
onNowHasData(newValue); onNowHasData(newValue);
} else }
else
LOG_DEBUG("(Client not yet interested in packets)\n"); LOG_DEBUG("(Client not yet interested in packets)\n");
return 0; return 0;

View File

@ -19,7 +19,8 @@
class PhoneAPI class PhoneAPI
: public Observer<uint32_t> // FIXME, we shouldn't be inheriting from Observer, instead use CallbackObserver as a member : public Observer<uint32_t> // FIXME, we shouldn't be inheriting from Observer, instead use CallbackObserver as a member
{ {
enum State { enum State
{
STATE_SEND_NOTHING, // Initial state, don't send anything until the client starts asking for config STATE_SEND_NOTHING, // Initial state, don't send anything until the client starts asking for config
STATE_SEND_MY_INFO, // send our my info record STATE_SEND_MY_INFO, // send our my info record
STATE_SEND_NODEINFO, // states progress in this order as the device sends to to the client STATE_SEND_NODEINFO, // states progress in this order as the device sends to to the client
@ -44,7 +45,7 @@ class PhoneAPI
meshtastic_MeshPacket *packetForPhone = NULL; meshtastic_MeshPacket *packetForPhone = NULL;
// file transfer packets destined for phone. Push it to the queue then free it. // file transfer packets destined for phone. Push it to the queue then free it.
meshtastic_XModem *xmodemPacketForPhone = NULL; meshtastic_XModem xmodemPacketForPhone = meshtastic_XModem_init_zero;
// Keep QueueStatus packet just as packetForPhone // Keep QueueStatus packet just as packetForPhone
meshtastic_QueueStatus *queueStatusPacketForPhone = NULL; meshtastic_QueueStatus *queueStatusPacketForPhone = NULL;
@ -58,7 +59,7 @@ class PhoneAPI
/// Use to ensure that clients don't get confused about old messages from the radio /// Use to ensure that clients don't get confused about old messages from the radio
uint32_t config_nonce = 0; uint32_t config_nonce = 0;
public: public:
PhoneAPI(); PhoneAPI();
/// Destructor - calls close() /// Destructor - calls close()
@ -91,7 +92,7 @@ class PhoneAPI
void setInitialState() { state = STATE_SEND_MY_INFO; } void setInitialState() { state = STATE_SEND_MY_INFO; }
protected: protected:
/// Our fromradio packet while it is being assembled /// Our fromradio packet while it is being assembled
meshtastic_FromRadio fromRadioScratch = {}; meshtastic_FromRadio fromRadioScratch = {};
@ -117,7 +118,7 @@ class PhoneAPI
*/ */
virtual void handleDisconnect(); virtual void handleDisconnect();
private: private:
void releasePhonePacket(); void releasePhonePacket();
void releaseQueueStatusPhonePacket(); void releaseQueueStatusPhonePacket();

View File

@ -36,13 +36,13 @@ XModemAdapter xModem;
XModemAdapter::XModemAdapter() XModemAdapter::XModemAdapter()
{ {
xmodemStore = (meshtastic_XModem *)malloc(meshtastic_XModem_size);
} }
unsigned short XModemAdapter::crc16_ccitt(const pb_byte_t *buffer, int length) unsigned short XModemAdapter::crc16_ccitt(const pb_byte_t *buffer, int length)
{ {
unsigned short crc16 = 0; unsigned short crc16 = 0;
while (length != 0) { while (length != 0)
{
crc16 = (unsigned char)(crc16 >> 8) | (crc16 << 8); crc16 = (unsigned char)(crc16 >> 8) | (crc16 << 8);
crc16 ^= *buffer; crc16 ^= *buffer;
crc16 ^= (unsigned char)(crc16 & 0xff) >> 4; crc16 ^= (unsigned char)(crc16 & 0xff) >> 4;
@ -66,32 +66,32 @@ int XModemAdapter::check(const pb_byte_t *buf, int sz, unsigned short tcrc)
void XModemAdapter::sendControl(meshtastic_XModem_Control c) void XModemAdapter::sendControl(meshtastic_XModem_Control c)
{ {
memset(xmodemStore, 0, meshtastic_XModem_size); xmodemStore = meshtastic_XModem_init_zero;
xmodemStore->control = c; xmodemStore.control = c;
LOG_DEBUG("XModem: Notify Sending control %d.\n", c); LOG_DEBUG("XModem: Notify Sending control %d.\n", c);
packetReady.notifyObservers(packetno); packetReady.notifyObservers(packetno);
} }
meshtastic_XModem *XModemAdapter::getForPhone() meshtastic_XModem XModemAdapter::getForPhone()
{ {
if (xmodemStore) {
return xmodemStore; return xmodemStore;
} else {
return NULL;
}
} }
void XModemAdapter::handlePacket(meshtastic_XModem xmodemPacket) void XModemAdapter::handlePacket(meshtastic_XModem xmodemPacket)
{ {
switch (xmodemPacket.control) { switch (xmodemPacket.control)
{
case meshtastic_XModem_Control_SOH: case meshtastic_XModem_Control_SOH:
case meshtastic_XModem_Control_STX: case meshtastic_XModem_Control_STX:
if ((xmodemPacket.seq == 0) && !isReceiving && !isTransmitting) { if ((xmodemPacket.seq == 0) && !isReceiving && !isTransmitting)
{
// NULL packet has the destination filename // NULL packet has the destination filename
memcpy(filename, &xmodemPacket.buffer.bytes, xmodemPacket.buffer.size); memcpy(filename, &xmodemPacket.buffer.bytes, xmodemPacket.buffer.size);
if (xmodemPacket.control == meshtastic_XModem_Control_SOH) { // Receive this file and put to Flash if (xmodemPacket.control == meshtastic_XModem_Control_SOH)
{ // Receive this file and put to Flash
file = FSCom.open(filename, FILE_O_WRITE); file = FSCom.open(filename, FILE_O_WRITE);
if (file) { if (file)
{
sendControl(meshtastic_XModem_Control_ACK); sendControl(meshtastic_XModem_Control_ACK);
isReceiving = true; isReceiving = true;
packetno = 1; packetno = 1;
@ -100,19 +100,23 @@ void XModemAdapter::handlePacket(meshtastic_XModem xmodemPacket)
sendControl(meshtastic_XModem_Control_NAK); sendControl(meshtastic_XModem_Control_NAK);
isReceiving = false; isReceiving = false;
break; break;
} else { // Transmit this file from Flash }
else
{ // Transmit this file from Flash
LOG_INFO("XModem: Transmitting file %s\n", filename); LOG_INFO("XModem: Transmitting file %s\n", filename);
file = FSCom.open(filename, FILE_O_READ); file = FSCom.open(filename, FILE_O_READ);
if (file) { if (file)
{
packetno = 1; packetno = 1;
isTransmitting = true; isTransmitting = true;
memset(xmodemStore, 0, meshtastic_XModem_size); xmodemStore = meshtastic_XModem_init_zero;
xmodemStore->control = meshtastic_XModem_Control_SOH; xmodemStore.control = meshtastic_XModem_Control_SOH;
xmodemStore->seq = packetno; xmodemStore.seq = packetno;
xmodemStore->buffer.size = file.read(xmodemStore->buffer.bytes, sizeof(meshtastic_XModem_buffer_t::bytes)); xmodemStore.buffer.size = file.read(xmodemStore.buffer.bytes, sizeof(meshtastic_XModem_buffer_t::bytes));
xmodemStore->crc16 = crc16_ccitt(xmodemStore->buffer.bytes, xmodemStore->buffer.size); xmodemStore.crc16 = crc16_ccitt(xmodemStore.buffer.bytes, xmodemStore.buffer.size);
LOG_DEBUG("XModem: STX Notify Sending packet %d, %d Bytes.\n", packetno, xmodemStore->buffer.size); LOG_DEBUG("XModem: STX Notify Sending packet %d, %d Bytes.\n", packetno, xmodemStore.buffer.size);
if (xmodemStore->buffer.size < sizeof(meshtastic_XModem_buffer_t::bytes)) { if (xmodemStore.buffer.size < sizeof(meshtastic_XModem_buffer_t::bytes))
{
isEOT = true; isEOT = true;
// send EOT on next Ack // send EOT on next Ack
} }
@ -123,11 +127,15 @@ void XModemAdapter::handlePacket(meshtastic_XModem xmodemPacket)
isTransmitting = false; isTransmitting = false;
break; break;
} }
} else { }
if (isReceiving) { else
{
if (isReceiving)
{
// normal file data packet // normal file data packet
if ((xmodemPacket.seq == packetno) && if ((xmodemPacket.seq == packetno) &&
check(xmodemPacket.buffer.bytes, xmodemPacket.buffer.size, xmodemPacket.crc16)) { check(xmodemPacket.buffer.bytes, xmodemPacket.buffer.size, xmodemPacket.crc16))
{
// valid packet // valid packet
file.write(xmodemPacket.buffer.bytes, xmodemPacket.buffer.size); file.write(xmodemPacket.buffer.bytes, xmodemPacket.buffer.size);
sendControl(meshtastic_XModem_Control_ACK); sendControl(meshtastic_XModem_Control_ACK);
@ -137,7 +145,9 @@ void XModemAdapter::handlePacket(meshtastic_XModem xmodemPacket)
// invalid packet // invalid packet
sendControl(meshtastic_XModem_Control_NAK); sendControl(meshtastic_XModem_Control_NAK);
break; break;
} else if (isTransmitting) { }
else if (isTransmitting)
{
// just received something weird. // just received something weird.
sendControl(meshtastic_XModem_Control_CAN); sendControl(meshtastic_XModem_Control_CAN);
isTransmitting = false; isTransmitting = false;
@ -160,8 +170,10 @@ void XModemAdapter::handlePacket(meshtastic_XModem xmodemPacket)
break; break;
case meshtastic_XModem_Control_ACK: case meshtastic_XModem_Control_ACK:
// Acknowledge Send the next packet // Acknowledge Send the next packet
if (isTransmitting) { if (isTransmitting)
if (isEOT) { {
if (isEOT)
{
sendControl(meshtastic_XModem_Control_EOT); sendControl(meshtastic_XModem_Control_EOT);
file.close(); file.close();
LOG_INFO("XModem: Finished sending file %s\n", filename); LOG_INFO("XModem: Finished sending file %s\n", filename);
@ -171,45 +183,53 @@ void XModemAdapter::handlePacket(meshtastic_XModem xmodemPacket)
} }
retrans = MAXRETRANS; // reset retransmit counter retrans = MAXRETRANS; // reset retransmit counter
packetno++; packetno++;
memset(xmodemStore, 0, meshtastic_XModem_size); xmodemStore = meshtastic_XModem_init_zero;
xmodemStore->control = meshtastic_XModem_Control_SOH; xmodemStore.control = meshtastic_XModem_Control_SOH;
xmodemStore->seq = packetno; xmodemStore.seq = packetno;
xmodemStore->buffer.size = file.read(xmodemStore->buffer.bytes, sizeof(meshtastic_XModem_buffer_t::bytes)); xmodemStore.buffer.size = file.read(xmodemStore.buffer.bytes, sizeof(meshtastic_XModem_buffer_t::bytes));
xmodemStore->crc16 = crc16_ccitt(xmodemStore->buffer.bytes, xmodemStore->buffer.size); xmodemStore.crc16 = crc16_ccitt(xmodemStore.buffer.bytes, xmodemStore.buffer.size);
LOG_DEBUG("XModem: ACK Notify Sending packet %d, %d Bytes.\n", packetno, xmodemStore->buffer.size); LOG_DEBUG("XModem: ACK Notify Sending packet %d, %d Bytes.\n", packetno, xmodemStore.buffer.size);
if (xmodemStore->buffer.size < sizeof(meshtastic_XModem_buffer_t::bytes)) { if (xmodemStore.buffer.size < sizeof(meshtastic_XModem_buffer_t::bytes))
{
isEOT = true; isEOT = true;
// send EOT on next Ack // send EOT on next Ack
} }
packetReady.notifyObservers(packetno); packetReady.notifyObservers(packetno);
} else { }
else
{
// just received something weird. // just received something weird.
sendControl(meshtastic_XModem_Control_CAN); sendControl(meshtastic_XModem_Control_CAN);
} }
break; break;
case meshtastic_XModem_Control_NAK: case meshtastic_XModem_Control_NAK:
// Negative acknowledge. Send the same buffer again // Negative acknowledge. Send the same buffer again
if (isTransmitting) { if (isTransmitting)
if (--retrans <= 0) { {
if (--retrans <= 0)
{
sendControl(meshtastic_XModem_Control_CAN); sendControl(meshtastic_XModem_Control_CAN);
file.close(); file.close();
LOG_INFO("XModem: Retransmit timeout, cancelling file %s\n", filename); LOG_INFO("XModem: Retransmit timeout, cancelling file %s\n", filename);
isTransmitting = false; isTransmitting = false;
break; break;
} }
memset(xmodemStore, 0, meshtastic_XModem_size); xmodemStore = meshtastic_XModem_init_zero;
xmodemStore->control = meshtastic_XModem_Control_SOH; xmodemStore.control = meshtastic_XModem_Control_SOH;
xmodemStore->seq = packetno; xmodemStore.seq = packetno;
file.seek((packetno - 1) * sizeof(meshtastic_XModem_buffer_t::bytes)); file.seek((packetno - 1) * sizeof(meshtastic_XModem_buffer_t::bytes));
xmodemStore->buffer.size = file.read(xmodemStore->buffer.bytes, sizeof(meshtastic_XModem_buffer_t::bytes)); xmodemStore.buffer.size = file.read(xmodemStore.buffer.bytes, sizeof(meshtastic_XModem_buffer_t::bytes));
xmodemStore->crc16 = crc16_ccitt(xmodemStore->buffer.bytes, xmodemStore->buffer.size); xmodemStore.crc16 = crc16_ccitt(xmodemStore.buffer.bytes, xmodemStore.buffer.size);
LOG_DEBUG("XModem: NAK Notify Sending packet %d, %d Bytes.\n", packetno, xmodemStore->buffer.size); LOG_DEBUG("XModem: NAK Notify Sending packet %d, %d Bytes.\n", packetno, xmodemStore.buffer.size);
if (xmodemStore->buffer.size < sizeof(meshtastic_XModem_buffer_t::bytes)) { if (xmodemStore.buffer.size < sizeof(meshtastic_XModem_buffer_t::bytes))
{
isEOT = true; isEOT = true;
// send EOT on next Ack // send EOT on next Ack
} }
packetReady.notifyObservers(packetno); packetReady.notifyObservers(packetno);
} else { }
else
{
// just received something weird. // just received something weird.
sendControl(meshtastic_XModem_Control_CAN); sendControl(meshtastic_XModem_Control_CAN);
} }

View File

@ -40,16 +40,16 @@
class XModemAdapter class XModemAdapter
{ {
public: public:
// Called when we put a fragment in the outgoing memory // Called when we put a fragment in the outgoing memory
Observable<uint32_t> packetReady; Observable<uint32_t> packetReady;
XModemAdapter(); XModemAdapter();
void handlePacket(meshtastic_XModem xmodemPacket); void handlePacket(meshtastic_XModem xmodemPacket);
meshtastic_XModem *getForPhone(); meshtastic_XModem getForPhone();
private: private:
bool isReceiving = false; bool isReceiving = false;
bool isTransmitting = false; bool isTransmitting = false;
bool isEOT = false; bool isEOT = false;
@ -66,8 +66,8 @@ class XModemAdapter
char filename[sizeof(meshtastic_XModem_buffer_t::bytes)] = {0}; char filename[sizeof(meshtastic_XModem_buffer_t::bytes)] = {0};
protected: protected:
meshtastic_XModem *xmodemStore = NULL; meshtastic_XModem xmodemStore = meshtastic_XModem_init_zero;
unsigned short crc16_ccitt(const pb_byte_t *buffer, int length); unsigned short crc16_ccitt(const pb_byte_t *buffer, int length);
int check(const pb_byte_t *buf, int sz, unsigned short tcrc); int check(const pb_byte_t *buf, int sz, unsigned short tcrc);
void sendControl(meshtastic_XModem_Control c); void sendControl(meshtastic_XModem_Control c);