diff --git a/src/vscp/common/mdf.cpp b/src/vscp/common/mdf.cpp index 6ae23bc9f..f65296fc2 100644 --- a/src/vscp/common/mdf.cpp +++ b/src/vscp/common/mdf.cpp @@ -1752,6 +1752,7 @@ CMDF::downLoadMDF(const std::string &url, const std::string &tempFileName) if (curl) { fp = fopen(tempFileName.c_str(), "wb"); curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); res = curl_easy_perform(curl); diff --git a/src/vscp/common/mdf.h b/src/vscp/common/mdf.h index 55111dd83..551fa8ef4 100644 --- a/src/vscp/common/mdf.h +++ b/src/vscp/common/mdf.h @@ -4119,7 +4119,7 @@ class CMDF : public CMDF_Object { @return Return CURLE_OK if a valid file is downloaded, else a curl error code. */ - CURLcode downLoadMDF(const std::string &remoteFile, const std::string &tempFile); + static CURLcode downLoadMDF(const std::string &remoteFile, const std::string &tempFile); /*! Load MDF from local or remote storage and parse it into diff --git a/src/vscp/common/vscp.h b/src/vscp/common/vscp.h index 0b1071277..d3a28c480 100644 --- a/src/vscp/common/vscp.h +++ b/src/vscp/common/vscp.h @@ -292,14 +292,14 @@ typedef VSCPChannelInfo *PVSCPCHANNELINFO; /* Interface types */ #define VSCP_INTERFACE_TYPE_UNKNOWN 0 -#define VSCP_INTERFACE_TYPE_INTERNAL 1 -#define VSCP_INTERFACE_TYPE_LEVEL1DRV 2 -#define VSCP_INTERFACE_TYPE_LEVEL2DRV 3 -#define VSCP_INTERFACE_TYPE_CLIENT_TCPIP 4 -#define VSCP_INTERFACE_TYPE_CLIENT_UDP 5 -#define VSCP_INTERFACE_TYPE_CLIENT_WEB 6 -#define VSCP_INTERFACE_TYPE_CLIENT_WEBSOCK 7 -#define VSCP_INTERFACE_TYPE_CLIENT_REST 8 +#define VSCP_INTERFACE_TYPE_INTERNAL 1 // Internal to daemon/server +#define VSCP_INTERFACE_TYPE_LEVEL1DRV 2 // Level I driver +#define VSCP_INTERFACE_TYPE_LEVEL2DRV 3 // Level II driver +#define VSCP_INTERFACE_TYPE_CLIENT_TCPIP 4 // TCP/IP client +#define VSCP_INTERFACE_TYPE_CLIENT_UDP 5 // UDP client +#define VSCP_INTERFACE_TYPE_CLIENT_WEB 6 // Web server +#define VSCP_INTERFACE_TYPE_CLIENT_WEBSOCK 7 // Websocket client +#define VSCP_INTERFACE_TYPE_CLIENT_REST 8 // REST client /* VSCP Encryption types */ #define VSCP_ENCRYPTION_NONE 0 diff --git a/src/vscp/common/vscp_bootdevice.cpp b/src/vscp/common/vscp_bootdevice.cpp index 84e59f4d1..63fa3f845 100644 --- a/src/vscp/common/vscp_bootdevice.cpp +++ b/src/vscp/common/vscp_bootdevice.cpp @@ -90,32 +90,39 @@ CBootMemBlock::~CBootMemBlock(void) CBootDevice::CBootDevice(CVscpClient *pclient, uint16_t nodeid, - std::function statusCallback, + std::function statusCallback, uint32_t timeout) { m_pclient = pclient; m_nodeid = nodeid; m_guid.clear(); + m_guid.setNicknameID(nodeid); m_guidif.clear(); m_timeout = timeout; m_statusCallback = statusCallback; + m_startAddr = 0; // Boot start } CBootDevice::CBootDevice(CVscpClient *pclient, uint16_t nodeid, cguid &guidif, - std::function statusCallback, + std::function statusCallback, uint32_t timeout) { m_pclient = pclient; m_nodeid = nodeid; m_guid.clear(); + m_guid.setNicknameID(nodeid); m_guidif = guidif; m_timeout = timeout; m_statusCallback = statusCallback; + m_startAddr = 0; // Boot start } -CBootDevice::CBootDevice(CVscpClient *pclient, cguid &guid, std::function statusCallback, uint32_t timeout) +CBootDevice::CBootDevice(CVscpClient *pclient, + cguid &guid, + std::function statusCallback, + uint32_t timeout) { m_pclient = pclient; m_nodeid = 0; @@ -123,6 +130,7 @@ CBootDevice::CBootDevice(CVscpClient *pclient, cguid &guid, std::function BOOT_MAX_BLOCK_SIZE) { - return VSCP_ERROR_SIZE; - } - // Fill block with void value (0xff for flash) memset(pblock, fill, size); diff --git a/src/vscp/common/vscp_bootdevice.h b/src/vscp/common/vscp_bootdevice.h index f9956fcea..efca6a63f 100644 --- a/src/vscp/common/vscp_bootdevice.h +++ b/src/vscp/common/vscp_bootdevice.h @@ -125,7 +125,7 @@ class CBootDevice { */ CBootDevice(CVscpClient *pclient, uint16_t nodeid, - std::function statusCallback = nullptr, + std::function statusCallback = nullptr, uint32_t timeout = REGISTER_DEFAULT_TIMEOUT); /*! @@ -140,7 +140,7 @@ class CBootDevice { CBootDevice(CVscpClient *pclient, uint16_t nodeid, cguid &guidif, - std::function statusCallback = nullptr, + std::function statusCallback = nullptr, uint32_t timeout = REGISTER_DEFAULT_TIMEOUT); /*! @@ -153,7 +153,7 @@ class CBootDevice { */ CBootDevice(CVscpClient *pclient, cguid &guid, - std::function statusCallback = nullptr, + std::function statusCallback = nullptr, uint32_t timeout = REGISTER_DEFAULT_TIMEOUT); /*! @@ -201,8 +201,11 @@ class CBootDevice { @param end Stop address for memory range (inclusive - end is part of address space) @param pmin Pointer to variable that will get min address @param pmax Pointer to variable that will get max address - @return VSCP_ERROR_SUCCESS on success. VSCP_ERROR_ERROR if no memory - defined in the selected range. + @return VSCP_ERROR_SUCCESS on success. + VSCP_ERROR_INVALID_POINTER if ponters are invalid. + VSCP_ERROR_INVALID_PARAMETER if end <= start + VSCP_ERROR_ERROR if no memory defined in the selected range. value of + pmin/pmax is zero in this case. */ virtual int getMinMaxForRange(uint32_t start, uint32_t end, uint32_t *pmin, uint32_t *pmax); @@ -224,9 +227,11 @@ class CBootDevice { /*! Set a device in bootmode + @param bAbortOnFirmwareCodeFail Set to true to fail if firmware code fetched from + MDF is not the same as the one read from the remote device. @return VSCP_ERROR_SUCCESS on success. */ - virtual int deviceInit(void) = 0; + virtual int deviceInit(bool bAbortOnFirmwareCodeFail = false) = 0; /*! Perform the actual firmware load process @@ -255,11 +260,11 @@ class CBootDevice { /*! Status callback - xxxxx(int, std::string) + xxxxx(int, const char *) int is percentage, str is real text description */ - std::function m_statusCallback; + std::function m_statusCallback; /*! The device code tell the type of hardware of the remote device @@ -286,6 +291,9 @@ class CBootDevice { /// Checksum for firmware uint32_t m_checksum; + // This is the minimum code address (startvector) + uint32_t m_startAddr; + /// # data bytes in file uint32_t m_totalCntData; diff --git a/src/vscp/common/vscp_bootdevice_pic1.cpp b/src/vscp/common/vscp_bootdevice_pic1.cpp index efcec8398..46c501ff5 100644 --- a/src/vscp/common/vscp_bootdevice_pic1.cpp +++ b/src/vscp/common/vscp_bootdevice_pic1.cpp @@ -34,11 +34,11 @@ #include "vscp_bootdevice_pic1.h" +#include "spdlog/fmt/bin_to_hex.h" #include #include #include #include -#include "spdlog/fmt/bin_to_hex.h" /////////////////////////////////////////////////////////////////////////////// // Constructor @@ -49,7 +49,7 @@ */ CBootDevice_PIC1::CBootDevice_PIC1(CVscpClient *pclient, uint8_t nodeid, - std::function statusCallback, + std::function statusCallback, uint32_t timeout) : CBootDevice(pclient, nodeid, statusCallback, timeout) { @@ -62,7 +62,7 @@ CBootDevice_PIC1::CBootDevice_PIC1(CVscpClient *pclient, CBootDevice_PIC1::CBootDevice_PIC1(CVscpClient *pclient, uint8_t nodeid, cguid &guidif, - std::function statusCallback, + std::function statusCallback, uint32_t timeout) : CBootDevice(pclient, nodeid, guidif, statusCallback, timeout) { @@ -74,7 +74,7 @@ CBootDevice_PIC1::CBootDevice_PIC1(CVscpClient *pclient, */ CBootDevice_PIC1::CBootDevice_PIC1(CVscpClient *pclient, cguid &guid, - std::function statusCallback, + std::function statusCallback, uint32_t timeout) : CBootDevice(pclient, guid, statusCallback, timeout) { @@ -93,7 +93,8 @@ CBootDevice_PIC1::~CBootDevice_PIC1(void) void CBootDevice_PIC1::init(void) { - m_bHandshake = true; // Handshake as default + m_bHandshake = true; // Handshake as default + m_startAddr = 0x800; // Default start position // m_pAddr = 0; // m_memtype = MEM_TYPE_PROGRAM; @@ -104,10 +105,10 @@ CBootDevice_PIC1::init(void) // m_bEepromMemory = false; // Reset block storage - memset(m_pbufCode, 0xff, BUFFER_SIZE_CODE); - memset(m_pbufUserID, 0xff, BUFFER_SIZE_USERID); - memset(m_pbufCfg, 0xff, BUFFER_SIZE_CONFIG); - memset(m_pbufEprom, 0xff, BUFFER_SIZE_EEPROM); + // memset(m_pbufCode, 0xff, BUFFER_SIZE_CODE); + // memset(m_pbufUserID, 0xff, BUFFER_SIZE_USERID); + // memset(m_pbufCfg, 0xff, BUFFER_SIZE_CONFIG); + // memset(m_pbufEprom, 0xff, BUFFER_SIZE_EEPROM); crcInit(); } @@ -223,13 +224,23 @@ CBootDevice_PIC1::deviceInfo(void) // int -CBootDevice_PIC1::deviceInit(void) +CBootDevice_PIC1::deviceInit(bool bAbortOnFirmwareCodeFail) { + int rv; + /* First do a test to see if the device is already in boot mode if it is 0x14nn/0x15nn should be returned (nn == nodeid). */ + spdlog::info("Test to see if remote device is already in boot mode."); + if (nullptr != m_statusCallback) { + m_statusCallback(-1, "Test to see if remote device is already in boot mode."); + } + + // Clear checksum + m_checksum = 0; + canalMsg msg, rcvmsg; time_t tstart, tnow; memset(msg.data, 0x00, 8); @@ -239,14 +250,23 @@ CBootDevice_PIC1::deviceInit(void) msg.flags = CANAL_IDFLAG_EXTENDED; memset(msg.data, 0, 8); msg.sizeData = 8; - if (CANAL_ERROR_SUCCESS != m_pclient->send(msg)) { - return VSCP_ERROR_COMMUNICATION; + if (CANAL_ERROR_SUCCESS != (rv = m_pclient->send(msg))) { + spdlog::error("Failed to send init message (ID_PUT_BASE_INFO) to remote device rv = {0}.", rv); + if (nullptr != m_statusCallback) { + m_statusCallback(-1, + vscp_str_format("Failed to send init message (ID_PUT_BASE_INFO) " + "to remote device rv = %d.", + rv) + .c_str()); + } + return rv; } time(&tstart); // Get start time bool bRun = true; while (bRun) { + time(&tnow); if ((unsigned long) (tnow - tstart) > 2) { bRun = false; // End loop @@ -256,17 +276,37 @@ CBootDevice_PIC1::deviceInit(void) if ((VSCP_ERROR_SUCCESS == m_pclient->getcount(&cnt)) && cnt) { // Check if data is available // There is data get message - m_pclient->receive(rcvmsg); + if (VSCP_ERROR_SUCCESS != (rv = m_pclient->receive(rcvmsg))) { + spdlog::error("Failed to receive reponse form init command (ID_PUT_BASE_INFO). rv = {0}.", rv); + if (nullptr != m_statusCallback) { + m_statusCallback(-1, + vscp_str_format("Failed to receive reponse form init command (ID_PUT_BASE_INFO). " + "rv = %d.", + rv) + .c_str()); + } + return rv; + } + + spdlog::debug("Initial probe: Received CAN message: id={0:X} size={1}", rcvmsg.id, rcvmsg.sizeData); // Is this a read/write reply from the node? if ((rcvmsg.id & 0xffffff) == (uint32_t) (ID_RESPONSE_PUT_BASE_INFO + m_nodeid)) { // yes already in bootmode - return + spdlog::info("Device is set in boot mode ID_RESPONSE_PUT_BASE_INFO"); + if (nullptr != m_statusCallback) { + m_statusCallback(-1, "Device is set in boot mode ID_RESPONSE_PUT_BASE_INFO"); + } return VSCP_ERROR_SUCCESS; } // Is this a read/write reply from the node? if ((rcvmsg.id & 0xffffff) == (uint32_t) (ID_RESPONSE_PUT_DATA + m_nodeid)) { // yes already in bootmode - return + spdlog::info("Device is set in boot mode ID_RESPONSE_PUT_DATA"); + if (nullptr != m_statusCallback) { + m_statusCallback(-1, "Device is set in boot mode ID_RESPONSE_PUT_DATA"); + } return VSCP_ERROR_SUCCESS; } } @@ -274,6 +314,7 @@ CBootDevice_PIC1::deviceInit(void) // Read standard registers if (VSCP_ERROR_SUCCESS != m_stdRegs.init(*m_pclient, m_guid, m_guidif, nullptr, REGISTER_DEFAULT_TIMEOUT)) { + spdlog::error("deviceInit: Failed to read standard registers"); return VSCP_ERROR_COMMUNICATION; } @@ -282,6 +323,10 @@ CBootDevice_PIC1::deviceInit(void) we offer */ if (VSCP_BOOTLOADER_PIC1 != m_stdRegs.getBootloaderAlgorithm()) { + spdlog::error("deviceInit: Bootloader algorithm is not Microchip PIC1"); + if (nullptr != m_statusCallback) { + m_statusCallback(-1, "Bootloader algorithm is not Microchip PIC1"); + } return VSCP_ERROR_NOT_SUPPORTED; } @@ -290,7 +335,15 @@ CBootDevice_PIC1::deviceInit(void) Must be the same as the firmware we try to load is intended for */ if (m_firmwaredeviceCode != m_stdRegs.getFirmwareDeviceCode()) { - return VSCP_ERROR_PARAMETER; + spdlog::warn("Firware device code is not equal the one on the device local: {0} device: {1}", + m_firmwaredeviceCode, + m_stdRegs.getFirmwareDeviceCode()); + if (nullptr != m_statusCallback) { + m_statusCallback(-1, "Firware device code is not equal the one on the device local: {0} device: {1}"); + } + if (bAbortOnFirmwareCodeFail) { + return VSCP_ERROR_PARAMETER; + } } // Set device in boot mode @@ -309,8 +362,12 @@ CBootDevice_PIC1::deviceInit(void) msg.id = (VSCP_PIC1_ENTER_BOOTLODER_MODE << 8); msg.flags = CANAL_IDFLAG_EXTENDED; msg.sizeData = 8; - if (CANAL_ERROR_SUCCESS != m_pclient->send(msg)) { - return VSCP_ERROR_COMMUNICATION; + if (CANAL_ERROR_SUCCESS != (rv = m_pclient->send(msg))) { + spdlog::error("deviceInit: Failed to send enter bootloader event {0}", rv); + if (nullptr != m_statusCallback) { + m_statusCallback(-1, "deviceInit: Failed to send enter bootloader event"); + } + return rv; } bRun = true; @@ -330,20 +387,32 @@ CBootDevice_PIC1::deviceInit(void) m_pclient->receive(rcvmsg); + spdlog::debug("Init boot mode: Received CAN message: id={0:X} size={1}", rcvmsg.id, rcvmsg.sizeData); + // Is this a read/write reply from the node? if ((rcvmsg.id & 0xffffff) == (uint32_t) (ID_RESPONSE_PUT_BASE_INFO + m_nodeid)) { // OK in bootmode - return + spdlog::debug("deviceInit: Confirmed, device is in boot mood."); + if (nullptr != m_statusCallback) { + m_statusCallback(-1, "deviceInit: Confirmed, device is in boot mood."); + } return VSCP_ERROR_SUCCESS; } // Is this a read/write reply from the node? if ((rcvmsg.id & 0xffffff) == (uint32_t) (ID_RESPONSE_PUT_DATA + m_nodeid)) { // OK in bootmode - return + spdlog::debug("deviceInit: Confirmed, device is in boot mood."); + if (nullptr != m_statusCallback) { + m_statusCallback(-1, "deviceInit: Confirmed, device is in boot mood."); + } return VSCP_ERROR_SUCCESS; } } } // while + return VSCP_ERROR_TIMEOUT; + /* vscpEventEx event; time_t tstart, tnow; @@ -489,100 +558,51 @@ CBootDevice_PIC1::writeDeviceControlRegs(uint32_t addr, uint8_t flags, uint8_t c int rv; vscpEventEx event; canalMsg msg; - /* - // Save the internal addresss - m_pAddr = addr; - - if ((m_pAddr < MEMREG_PRG_END) && (m_pAddr < BUFFER_SIZE_PROGRAM)) { - - // Flash memory - m_memtype = MEM_TYPE_PROGRAM; - } - else if ((m_pAddr >= MEMREG_CONFIG_START) && ((m_pAddr < MEMREG_CONFIG_START + BUFFER_SIZE_CONFIG))) { - - // Config memory - m_memtype = MEM_TYPE_CONFIG; - } - else if ((m_pAddr >= MEMREG_EEPROM_START) && ((m_pAddr <= MEMREG_EEPROM_START + BUFFER_SIZE_EEPROM))) { - - // EEPROM - m_memtype = MEM_TYPE_EEPROM; - } - else { - return false; - } - if (USE_DLL_INTERFACE == m_type) { - - msg.id = ID_PUT_BASE_INFO; - msg.flags = CANAL_IDFLAG_EXTENDED; - msg.sizeData = 8; - msg.id += m_nodeid; // Add node id. - msg.data[0] = (unsigned char) (addr & 0xff); - msg.data[1] = (unsigned char) ((addr >> 8) & 0xff); - msg.data[2] = (unsigned char) ((addr >> 16) & 0xff); - msg.data[3] = 0; - msg.data[4] = flags; - msg.data[5] = cmd; - msg.data[6] = cmdData0; - msg.data[7] = cmdData1; - } - else if (USE_TCPIP_INTERFACE == m_type) { - - event.head = 0; - event.vscp_class = 512; // CLASS2.PROTOCOL1 - event.vscp_type = ID_PUT_BASE_INFO >> 8; - memset(event.GUID, 0, 16); // We use interface GUID - event.sizeData = 16 + 8; // Interface GUID - memcpy(event.data, m_guidif.m_id, 16); // Address node in i/f - event.data[16] = (unsigned char) (addr & 0xff); - event.data[17] = (unsigned char) ((addr >> 8) & 0xff); - event.data[18] = (unsigned char) ((addr >> 16) & 0xff); - event.data[19] = 0; - event.data[20] = flags; - event.data[21] = cmd; - event.data[22] = cmdData0; - event.data[23] = cmdData1; - } - else { - return false; - } - - if (flags & MODE_ACK) { - m_bHandshake = true; - } - else { - m_bHandshake = false; - } + // Save the internal addresss + m_pAddr = addr; - // Send message - if (USE_DLL_INTERFACE == m_type) { + msg.id = ID_PUT_BASE_INFO; + msg.flags = CANAL_IDFLAG_EXTENDED; + msg.sizeData = 8; + msg.id += m_nodeid; // Add node id. + msg.data[0] = (unsigned char) (addr & 0xff); + msg.data[1] = (unsigned char) ((addr >> 8) & 0xff); + msg.data[2] = (unsigned char) ((addr >> 16) & 0xff); + msg.data[3] = (unsigned char) ((addr >> 24 & 0xff)); // Ignored by remote device + msg.data[4] = flags; + msg.data[5] = cmd; + msg.data[6] = cmdData0; + msg.data[7] = cmdData1; + + if (flags & MODE_ACK) { + m_bHandshake = true; + } + else { + m_bHandshake = false; + } - if (CANAL_ERROR_SUCCESS == m_pclient->send(msg)) { + if (VSCP_ERROR_SUCCESS == (rv = m_pclient->send(msg))) { - // Message queued - ( wait for response from client(s) ). - if (m_bHandshake) { - rv = checkResponseLevel1(ID_RESPONSE_PUT_BASE_INFO); + // Message queued - ( wait for response from client(s) ). + if (m_bHandshake) { + if (VSCP_ERROR_SUCCESS != (rv = checkResponseLevel1(ID_RESPONSE_PUT_BASE_INFO))) { + spdlog::error("writeDeviceControlRegs: Timeout while waiting for response from device."); + if (nullptr != m_statusCallback) { + m_statusCallback(-1, "writeDeviceControlRegs: Timeout while waiting for response from device."); } - } - else { - rv = false; + return rv; } } - else { - - if (CANAL_ERROR_SUCCESS == m_pclient->send(event)) { - - // Message queued - ( wait for response from client(s) ). - if (m_bHandshake) { - rv = checkResponseLevel2(ID_RESPONSE_PUT_BASE_INFO); - } - } - else { - rv = false; - } + } + else { + spdlog::error("writeDeviceControlRegs: Failed to send boot command to remote device."); + if (nullptr != m_statusCallback) { + m_statusCallback(-1, "writeDeviceControlRegs: Failed to send boot command to remote device."); } - */ + return rv; + } + return VSCP_ERROR_SUCCESS; } @@ -604,19 +624,18 @@ CBootDevice_PIC1::checkResponseLevel1(uint32_t response_id) while (bRun) { if (CANAL_ERROR_SUCCESS == (rv = m_pclient->receive(msg))) { - spdlog::trace("checkResponseLevel1: < id={:X} {:n}", msg.id, spdlog::to_hex(msg.data, msg.data + 7)); + spdlog::debug("checkResponseLevel1: RECEIVE id={:X} {:n}", msg.id, spdlog::to_hex(msg.data, msg.data + 7)); if (((msg.id & 0xffffff00) == response_id)) { // correct id if ((int) (msg.id & 0xff) == m_nodeid) { // from correct node // Response received from all - return success - spdlog::trace("checkResponseLevel1: < OK"); + spdlog::debug("checkResponseLevel1: RECEIVE OK"); + if (nullptr != m_statusCallback) { + //m_statusCallback(-1, "checkResponseLevel1: Response received OK."); + } return VSCP_ERROR_SUCCESS; } } } - else { - spdlog::error("checkResponseLevel1: failed to receive data {}", rv); - return rv; - } // check for timeout time(&tnow); @@ -626,6 +645,10 @@ CBootDevice_PIC1::checkResponseLevel1(uint32_t response_id) } spdlog::error("checkResponseLevel1: Timeout {}", rv); + if (nullptr != m_statusCallback) { + m_statusCallback(-1, "checkResponseLevel1: Timout waiting while for response"); + } + return VSCP_ERROR_TIMEOUT; } @@ -647,16 +670,19 @@ CBootDevice_PIC1::checkResponseLevel2(uint32_t id) while (bRun) { if (VSCP_ERROR_SUCCESS == (rv = m_pclient->receive(ex))) { - if ((VSCP_CLASS1_PROTOCOL == ex.vscp_class) && (m_guid.getLSB() == ex.GUID[15])) { // correct id - // Response received - return success - return VSCP_ERROR_SUCCESS; - } - } - else { spdlog::error("checkResponseLevel2: failed to receive data {}", rv); return rv; } + if ((VSCP_CLASS1_PROTOCOL == ex.vscp_class) && (m_guid.getLSB() == ex.GUID[15])) { // correct id + // Response received - return success + spdlog::debug("checkResponseLevel2: RECEIVE OK"); + if (nullptr != m_statusCallback) { + //m_statusCallback(-1, "checkResponseLevel2: Response received OK."); + } + return VSCP_ERROR_SUCCESS; + } + // check for timeout time(&tnow); if ((tnow - tstart) > PIC_BOOTLOADER_RESPONSE_TIMEOUT) { @@ -664,6 +690,11 @@ CBootDevice_PIC1::checkResponseLevel2(uint32_t id) } } + spdlog::error("checkResponseLevel2: Timeout {}", rv); + if (nullptr != m_statusCallback) { + m_statusCallback(-1, "checkResponseLevel2: Timout waiting while for response"); + } + return VSCP_ERROR_TIMEOUT; } @@ -693,14 +724,17 @@ CBootDevice_PIC1::writeFirmwareSector(uint8_t *paddr) m_checksum += paddr[i]; }; - spdlog::trace("writeFirmwareSector: > {:n}", spdlog::to_hex(msg.data, msg.data + 7)); - // send if (VSCP_ERROR_SUCCESS != (rv = m_pclient->send(msg))) { spdlog::error("PIC1 Firmware load: writeFirmwareSector: Failed to send CANAL message rv={} ", rv); + if (nullptr != m_statusCallback) { + m_statusCallback(-1, vscp_str_format("writeFirmwareSector: Failed to send CANAL message rv=%d", rv).c_str()); + } return rv; } + spdlog::debug("writeFirmwareSector: SEND {0:n}", spdlog::to_hex(msg.data, msg.data + 7)); + if (m_bHandshake) { return checkResponseLevel1(ID_RESPONSE_PUT_DATA); } @@ -720,11 +754,14 @@ CBootDevice_PIC1::writeFirmwareSector(uint8_t *paddr) m_checksum += paddr[i]; }; - spdlog::trace("writeFirmwareSector: > {:n}", spdlog::to_hex(ex.data, ex.data + 16+7)); + spdlog::debug("writeFirmwareSector: > {:n}", spdlog::to_hex(ex.data, ex.data + 16 + 7)); // Send if (VSCP_ERROR_SUCCESS != (rv = m_pclient->send(ex))) { spdlog::error("PIC1 Firmware load: writeFirmwareSector: Failed to send CANAL message rv={} ", rv); + if (nullptr != m_statusCallback) { + m_statusCallback(-1, vscp_str_format("writeFirmwareSector: Failed to send CANAL message rv=%d", rv).c_str()); + } return rv; } @@ -750,46 +787,81 @@ CBootDevice_PIC1::writeFirmwareBlock(uint32_t start, uint32_t end) uint32_t nPackets; uint8_t *pbuf, *paddr; - pbuf = paddr = new uint8_t[size]; + // If size is zero we are done + if (!size) { + return VSCP_ERROR_SUCCESS; + } + + pbuf = new uint8_t[size]; + paddr = pbuf; if (nullptr == pbuf) { return VSCP_ERROR_MEMORY; } - if (VSCP_ERROR_SUCCESS != (rv = getMinMaxForRange(MEM_CODE_START, MEM_CODE_END, &minAddr, &maxAddr))) { + if (VSCP_ERROR_SUCCESS != (rv = getMinMaxForRange(start, end, &minAddr, &maxAddr))) { + delete[] pbuf; + spdlog::error("writeFirmwareBlock: Failed to get min max range for block {0:X}-{1:X}", start, end); + if (nullptr != m_statusCallback) { + m_statusCallback(-1, vscp_str_format("writeFirmwareBlock: Failed to get min max range for block", rv).c_str()); + } return rv; } + // Nothing to do? + if ((0 == minAddr) && (0 == maxAddr)) { + delete[] pbuf; + return VSCP_ERROR_SUCCESS; + } + if (maxAddr > minAddr) { nPackets = (maxAddr - minAddr) / 8; - // A not completly full packet also count + // A not completely full packet also count if (0 != ((maxAddr - minAddr) % 8)) { nPackets++; } // Init the block - if (VSCP_ERROR_SUCCESS != (rv = fillBlock(pbuf, sizeof(pbuf), MEM_CODE_START))) { - spdlog::error("Failed to send control info for flash data to node(s)."); + if (VSCP_ERROR_SUCCESS != (rv = fillBlock(pbuf, size, start))) { + spdlog::error("writeFirmwareBlock: Failed to fill code block with data."); + if (nullptr != m_statusCallback) { + m_statusCallback(-1, + vscp_str_format("writeFirmwareBlock: Failed to fill code block with data rv=%d", rv).c_str()); + } + delete[] pbuf; return rv; } // Send the start block if (VSCP_ERROR_SUCCESS != (rv = writeDeviceControlRegs(minAddr))) { - spdlog::error("Failed to send start block for flash data to node(s)."); + spdlog::error("Failed to send start block for flash data to remote device."); + if (nullptr != m_statusCallback) { + m_statusCallback( + -1, + vscp_str_format("writeFirmwareBlock: Failed to send start block for flash data to remote device. rv=%d", rv) + .c_str()); + } + delete[] pbuf; return rv; } - for (uint32_t blk = 0; blk < nPackets; blk++) { - - spdlog::trace("Loading flash... block={0} {:X}", minAddr + (8 * blk)); + // Start at beginning + paddr += minAddr-start; + for (uint32_t blk = 0; blk < nPackets; blk++) { + spdlog::debug("Loading flash on remote device... block={0} {1:X}", blk, blk * 8); if (VSCP_ERROR_SUCCESS != writeFirmwareSector(paddr)) { spdlog::error("Failed to write flash data to node(s)."); break; } paddr += 8; + if (nullptr != m_statusCallback) { + m_statusCallback((100 * blk) / nPackets, ""/*vscp_str_format("blk %d.", blk).c_str()*/); + } + } // for } // code + delete[] pbuf; return VSCP_ERROR_SUCCESS; } @@ -813,215 +885,109 @@ CBootDevice_PIC1::deviceLoad(std::function statusCallba uint32_t minAddr; uint32_t maxAddr; - if (!writeDeviceControlRegs(addr, MODE_WRT_UNLCK | MODE_AUTO_ERASE | MODE_AUTO_INC | MODE_ACK, CMD_RST_CHKSM, 0, 0)) { + if (nullptr != m_statusCallback) { + m_statusCallback(0, "Starting firmware download"); + } + + if (VSCP_ERROR_SUCCESS != + writeDeviceControlRegs(addr, MODE_WRT_UNLCK | MODE_AUTO_ERASE | MODE_AUTO_INC | MODE_ACK, CMD_RST_CHKSM, 0, 0)) { spdlog::error("Failed to initialize checksum at node(s)."); + if (nullptr != m_statusCallback) { + m_statusCallback(0, "Failed to initialize checksum at node(s)."); + } return VSCP_ERROR_COMMUNICATION; } // * * * * Flash memory * * * * if (VSCP_ERROR_SUCCESS != (rv = writeFirmwareBlock(MEM_CODE_START, MEM_CODE_END))) { + spdlog::error("Failed to write flash block."); + if (nullptr != m_statusCallback) { + m_statusCallback(-1, "Failed to write flash block."); + } return rv; } - // * * * * Flash memory * * * * - - // * * * * EEPROM * * * * - if (VSCP_ERROR_SUCCESS != (rv = writeFirmwareBlock(MEM_EEPROM_START, MEM_EEPROM_END))) { + // * * * * User id * * * * + if (VSCP_ERROR_SUCCESS != (rv = writeFirmwareBlock(MEM_USERID_START, MEM_USERID_END))) { + spdlog::error("Failed to write user id block."); + if (nullptr != m_statusCallback) { + m_statusCallback(-1, "Failed to write user id block."); + } return rv; } - /* - - // wxProgressDialog *pDlg = - // new wxProgressDialog(_T("Boot loading in progress..."), - // _T("---"), - // nTotalPackets, - // NULL, - // wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT | wxPD_ELAPSED_TIME | - wxPD_REMAINING_TIME); - - // Initialize checksum - addr = m_minFlashAddr; - if (!writeDeviceControlRegs(addr, MODE_WRT_UNLCK | MODE_AUTO_ERASE | MODE_AUTO_INC | MODE_ACK, CMD_RST_CHKSM, 0, - 0)) { wxMessageBox(_T("Failed to initialize checksum at node(s).")); rv = false; bRun = false; + // * * * * Config * * * * + if (VSCP_ERROR_SUCCESS != (rv = writeFirmwareBlock(MEM_CONFIG_START, MEM_CONFIG_END))) { + spdlog::error("Failed to write user id block."); + if (nullptr != m_statusCallback) { + m_statusCallback(-1, "Failed to write user id block."); } + return rv; + } - // * * * flash memory * * * - - if (rv && m_bCodeData) { - - // Send the start block - addr = m_minFlashAddr; - if (writeDeviceControlRegs(addr)) { - - for (unsigned long blk = 0; ((blk < nFlashPackets) && bRun); blk++) { - - wxStatusStr.Printf(_("Loading flash... %0X"), addr); - if (!(bRun = pDlg->Update(progress, wxStatusStr))) { - wxMessageBox(_T("Aborted by user.")); - rv = false; - bRun = false; - } - - if (!writeFrimwareSector()) { - wxMessageBox(_T("Failed to write flash data to node(s).")); - rv = false; - bRun = false; - } - - wxMilliSleep(1); - progress++; - addr += 8; - } - } - else { - wxMessageBox(_T("Failed to send control info for flash data to node(s).")); - rv = false; - } + // * * * * EEPROM * * * * + if (VSCP_ERROR_SUCCESS != (rv = writeFirmwareBlock(MEM_EEPROM_START, MEM_EEPROM_END))) { + spdlog::error("Failed to write user id block."); + if (nullptr != m_statusCallback) { + m_statusCallback(-1, "Failed to write user id block."); } + return rv; + } - // * * * config memory * * * - - if (rv && m_bCfgData) { - - // Send the start block - addr = m_minConfigAddr; - if (writeDeviceControlRegs(addr)) { - - for (unsigned long blk = 0; ((blk < nConfigPackets) && bRun); blk++) { + return VSCP_ERROR_SUCCESS; +} - wxStatusStr.Printf(_("Loading config memory... %0X"), addr); - if (!(bRun = pDlg->Update(progress, wxStatusStr))) { - wxMessageBox(_T("Aborted by user.")); - rv = false; - bRun = false; - } +/////////////////////////////////////////////////////////////////////////////// +// deviceRestart +// - if (!writeFrimwareSector()) { - wxMessageBox(_T("Failed to write config data to node(s).")); - rv = false; - bRun = false; - } +int +CBootDevice_PIC1::deviceRestart(void) +{ + int rv; + uint32_t min, max; - wxMilliSleep(1); - progress++; - addr += 8; - } - } - else { - wxMessageBox(_T("Failed to send control info for config data to node(s).")); - rv = false; - } + if (VSCP_ERROR_SUCCESS != + getMinMaxForRange(CBootDevice_PIC1::MEM_CODE_START, CBootDevice_PIC1::MEM_CODE_END, &min, &max)) { + spdlog::warn("deviceRestart: Failed to get start address. Use default."); + if (nullptr != m_statusCallback) { + m_statusCallback(-1, "deviceRestart: Failed to get start flash address."); } + } - // * * * EEPROM memory * * * - - if (rv && m_bEepromData) { - - // Send the start block - addr = m_minEEPROMAddr; - if (writeDeviceControlRegs(addr)) { - - for (unsigned long blk = 0; ((blk < nConfigPackets) && bRun); blk++) { - - wxStatusStr.Printf(_("Loading EEPROM memory... %0X"), addr); - if (!(bRun = pDlg->Update(progress, wxStatusStr))) { - // wxMessageBox(_T("Aborted by user.")); - rv = false; - bRun = false; - } - - if (!writeFrimwareSector()) { - // wxMessageBox(_T("Failed to write EEPROM data to node(s).")); - rv = false; - bRun = false; - } + m_startAddr = min; - wxMilliSleep(1); - progress++; - addr += 8; - } - } - else { - // wxMessageBox( _T("Failed to send control info for EEPROM data to - // node(s).") ); - rv = false; - } + // Check if checksum is correct and reset device(s) + uint16_t calc_chksum = (0x10000 - (m_checksum & 0xffff)); + if (VSCP_ERROR_SUCCESS != (rv = writeDeviceControlRegs(m_startAddr, + MODE_WRT_UNLCK | MODE_AUTO_ERASE | MODE_ACK, + CMD_CHK_RUN, + (calc_chksum & 0xff), + ((calc_chksum >> 8) & 0xff)))) { + spdlog::warn("deviceRestart: Failed to checksum restart device.rv={}.", rv); + if (nullptr != m_statusCallback) { + m_statusCallback(-1, vscp_str_format("deviceRestart: Failed to checksum restart device.rv=%d", rv).c_str()); } + return rv; + } - if (rv) { - - // Check if checksum is correct and reset device(s) - addr = m_minFlashAddr; - uint16_t calc_chksum = (0x10000 - (m_checksum & 0xffff)); - if (!writeDeviceControlRegs(addr, - MODE_WRT_UNLCK | MODE_AUTO_ERASE | MODE_ACK, - CMD_CHK_RUN, - (calc_chksum & 0xff), - ((calc_chksum >> 8) & 0xff))) { - // wxMessageBox( _T( "Failed to do finalizing and restart at - // node(s).Possible checksum error." ) ); - rv = false; - bRun = false; - } - else { - - bool bReady = false; - - // Do the device RESET - writeDeviceControlRegs(0x0000, 0, CMD_RESET, 0, 0); - - pDlg->Update(progress, _("Reset sent.")); - - sleep(5); - - // No use to check if we got out of bootloader mode if id is init. - // id. - if (((USE_DLL_INTERFACE == m_type) && (0xfe != m_nodeid)) || - ((USE_TCPIP_INTERFACE == m_type) && (0xfe != m_guid.getAt(15)))) { - - for (int i = 0; i < 3; i++) { - - // Do the device RESET - writeDeviceControlRegs(0x0000, 0, CMD_RESET, 0, 0); - - std::string str = std::string::Format(_("Trying to verify restart %d"), i); - pDlg->Update(progress, str); - - sleep(5); - - // Verify that clients got out of boot mode. - // If we can read register we are ready - unsigned char val; + return VSCP_ERROR_SUCCESS; +} - if (USE_DLL_INTERFACE == m_type) { - if (CANAL_ERROR_SUCCESS == m_pclient->readLevel1Register(m_nodeid, 0, VSCP_REG_GUID0, &val)) { - bReady = true; - break; - } - } - else if (USE_TCPIP_INTERFACE == m_type) { - if (VSCP_ERROR_SUCCESS == m_pclient->readLevel2Register(VSCP_REG_GUID0, 0, &val, m_guidif, &m_guid)) { - bReady = true; - break; - } - } - } - } +/////////////////////////////////////////////////////////////////////////////// +// deviceReboot +// - if (!bReady) { - pDlg->Update(progress, _("Could not verify that device came out of reset.")); - // wxMessageBox(_T( "Could not verify that device came out of reset." )); - rv = false; - } - } +int +CBootDevice_PIC1::deviceReboot(void) +{ + int rv; + if (VSCP_ERROR_SUCCESS != (rv = writeDeviceControlRegs(0x0000, 0, CMD_RESET, 0, 0))) { + spdlog::warn("deviceRestart: Failed to reboot device.rv={}.", rv); + if (nullptr != m_statusCallback) { + m_statusCallback(-1, vscp_str_format("deviceReboot: Failed to reboot device.rv=%d", rv).c_str()); } - - // Done - progress = nTotalPackets; - pDlg->Update(progress, wxStatusStr); - - pDlg->Destroy(); - */ + return rv; + } return VSCP_ERROR_SUCCESS; } diff --git a/src/vscp/common/vscp_bootdevice_pic1.h b/src/vscp/common/vscp_bootdevice_pic1.h index 453d49737..3ed3c9f0b 100644 --- a/src/vscp/common/vscp_bootdevice_pic1.h +++ b/src/vscp/common/vscp_bootdevice_pic1.h @@ -52,8 +52,8 @@ class CBootDevice_PIC1 : public CBootDevice { */ CBootDevice_PIC1(CVscpClient *pclient, uint8_t nodeid, - std::function statusCallback = nullptr, - uint32_t timeout = REGISTER_DEFAULT_TIMEOUT); + std::function statusCallback = nullptr, + uint32_t timeout = REGISTER_DEFAULT_TIMEOUT); /*! Constructor @@ -69,8 +69,8 @@ class CBootDevice_PIC1 : public CBootDevice { CBootDevice_PIC1(CVscpClient *pclient, uint8_t nodeid, cguid &guidif, - std::function statusCallback = nullptr, - uint32_t timeout = REGISTER_DEFAULT_TIMEOUT); + std::function statusCallback = nullptr, + uint32_t timeout = REGISTER_DEFAULT_TIMEOUT); /*! Constructor @@ -82,8 +82,8 @@ class CBootDevice_PIC1 : public CBootDevice { */ CBootDevice_PIC1(CVscpClient *pclient, cguid &guid, - std::function statusCallback = nullptr, - uint32_t timeout = REGISTER_DEFAULT_TIMEOUT); + std::function statusCallback = nullptr, + uint32_t timeout = REGISTER_DEFAULT_TIMEOUT); // Dtor ~CBootDevice_PIC1(void); @@ -98,7 +98,7 @@ class CBootDevice_PIC1 : public CBootDevice { // Flash memory static const uint32_t MEM_CODE_START = 0x000000; - static const uint32_t MEM_CODE_END = 0x2fffff; + static const uint32_t MEM_CODE_END = 0x1fffff; /* User IDs (starting at address 200000h) are considered @@ -106,6 +106,7 @@ class CBootDevice_PIC1 : public CBootDevice { erased like normal FLASH Program Memory. */ static const uint32_t MEM_USERID_START = 0x200000; + static const uint32_t MEM_USERID_END = 0x2fffff; // Configuration memory static const uint32_t MEM_CONFIG_START = 0x300000; @@ -176,15 +177,17 @@ class CBootDevice_PIC1 : public CBootDevice { /*! Show info for hex file - @param Pointer to HTML window that will receive information. + @return String that will receive information. */ std::string deviceInfo(void); /*! Initialize boot mode, ie set device in bootmode + @param bAbortOnFirmwareCodeFail Set to true to fail if firmware code fetched from + MDF is not the same as the one read from the remote device. @return VSCP_ERROR_SUCCESS on success. */ - int deviceInit(void); + int deviceInit(bool bAbortOnFirmwareCodeFail = false); /*! Write a boot block to the device @@ -202,6 +205,18 @@ class CBootDevice_PIC1 : public CBootDevice { */ int deviceLoad(std::function statusCallback = nullptr); + /*! + Restart remote device + @return VSCP_ERROR_SUCCESS is returned on success, ortherwise error code + */ + int deviceRestart(void); + + /*! + Reboot remote device + @return VSCP_ERROR_SUCCESS is returned on success, ortherwise error code + */ + int deviceReboot(void); + /*! Write a sector @param paddr Pointer to firts byte of 8-byte block to write @@ -259,31 +274,9 @@ class CBootDevice_PIC1 : public CBootDevice { /// Flag for handshake with node bool m_bHandshake; + /// Code checksum + uint16_t m_checksum; + /// Internal address pointer uint32_t m_pAddr; - - /// memory type - // uint8_t m_memtype; - - /// Min and max mem blocks - // uint32_t m_minFlashAddr; - // uint32_t m_maxFlashAddr; - // uint32_t m_minUserIdAddr; - // uint32_t m_maxUserIdAddr; - // uint32_t m_minConfigAddr; - // uint32_t m_maxConfigAddr; - // uint32_t m_minEEPROMAddr; - // uint32_t m_maxEEPROMAddr; - - // Flags for code in codeblocks (false as default) - // bool m_bCodeMemory; - // bool m_bUserIdMemory; - // bool m_bCfgMemory; - // bool m_bEepromMemory; - - // Pic 1 memory buffers - uint8_t m_pbufCode[BUFFER_SIZE_CODE]; - uint8_t m_pbufUserID[BUFFER_SIZE_USERID]; - uint8_t m_pbufCfg[BUFFER_SIZE_CONFIG]; - uint8_t m_pbufEprom[BUFFER_SIZE_EEPROM]; }; diff --git a/src/vscp/common/vscp_client_mqtt.cpp b/src/vscp/common/vscp_client_mqtt.cpp index b2038fd55..db8304344 100644 --- a/src/vscp/common/vscp_client_mqtt.cpp +++ b/src/vscp/common/vscp_client_mqtt.cpp @@ -147,7 +147,7 @@ mqtt_on_connect(struct mosquitto *mosq, void *pData, int rv) vscpClientMqtt *pClient = reinterpret_cast(pData); pClient->m_bConnected = true; - spdlog::info("MQTT CLIENT: MQTT v3.11 connect: rv={0:X} flags={1:X} {2}", rv, mosquitto_strerror(rv)); + spdlog::debug("MQTT CLIENT: v3.11 connect: rv={0:X} flags={1:X} {2}", rv, mosquitto_strerror(rv)); if (nullptr != pClient->m_parentCallbackConnect) { pClient->m_parentCallbackConnect(mosq, pClient->m_pParent, rv); @@ -175,7 +175,7 @@ mqtt_on_connect_flags(struct mosquitto *mosq, void *pData, int rv, int flags) vscpClientMqtt *pClient = reinterpret_cast(pData); pClient->m_bConnected = true; - spdlog::info("MQTT CLIENT: MQTT v3.11 connect: rv={0:X} flags={1:X} {2}", rv, flags, mosquitto_strerror(rv)); + spdlog::debug("MQTT CLIENT: v3.11 connect: rv={0:X} flags={1:X} {2}", rv, flags, mosquitto_strerror(rv)); if (nullptr != pClient->m_parentCallbackConnect) { pClient->m_parentCallbackConnect(mosq, pClient->m_pParent, rv); @@ -203,7 +203,7 @@ mqtt_on_connect_v5(struct mosquitto *mosq, void *pData, int rv, int flags, const vscpClientMqtt *pClient = reinterpret_cast(pData); pClient->m_bConnected = true; - spdlog::info("MQTT CLIENT: MQTT v5 connect: rv={0:X} flags={1:X} {2}", rv, flags, mosquitto_strerror(rv)); + spdlog::debug("MQTT CLIENT: MQTT v5 connect: rv={0:X} flags={1:X} {2}", rv, flags, mosquitto_strerror(rv)); if (nullptr != pClient->m_parentCallbackConnect) { pClient->m_parentCallbackConnect(mosq, pClient->m_pParent, rv); @@ -231,7 +231,7 @@ mqtt_on_disconnect(struct mosquitto *mosq, void *pData, int rv) vscpClientMqtt *pClient = reinterpret_cast(pData); pClient->m_bConnected = false; - spdlog::info("MQTT CLIENT: MQTT v3.11 disconnect: rv={0:X} {1}", rv, mosquitto_strerror(rv)); + spdlog::debug("MQTT CLIENT: MQTT v3.11 disconnect: rv={0:X} {1}", rv, mosquitto_strerror(rv)); if (nullptr != pClient->m_parentCallbackDisconnect) { pClient->m_parentCallbackDisconnect(mosq, pClient->m_pParent, rv); @@ -259,7 +259,7 @@ mqtt_on_disconnect_v5(struct mosquitto *mosq, void *pData, int rv, const mosquit vscpClientMqtt *pClient = reinterpret_cast(pData); pClient->m_bConnected = false; - spdlog::trace("MQTT CLIENT: MQTT v5 disconnect: rv={0:X} {1}", rv, mosquitto_strerror(rv)); + spdlog::debug("MQTT CLIENT: MQTT v5 disconnect: rv={0:X} {1}", rv, mosquitto_strerror(rv)); if (nullptr != pClient->m_parentCallbackDisconnect) { pClient->m_parentCallbackDisconnect(mosq, pClient->m_pParent, rv); @@ -285,7 +285,7 @@ mqtt_on_publish(struct mosquitto *mosq, void *pData, int mid) } vscpClientMqtt *pClient = reinterpret_cast(pData); - spdlog::trace("MQTT publish: MQTT v3.11 publish: mid={0:X}", mid); + spdlog::debug("MQTT publish: MQTT v3.11 publish: mid={0:X}", mid); if (nullptr != pClient->m_parentCallbackPublish) { pClient->m_parentCallbackPublish(mosq, pClient->m_pParent, mid); @@ -311,7 +311,7 @@ mqtt_on_publish_v5(struct mosquitto *mosq, void *pData, int mid, int reason_code } vscpClientMqtt *pClient = reinterpret_cast(pData); - spdlog::trace("MQTT publish: MQTT v5 publish: mid={0:X} reason-code={1:X}", mid, reason_code); + spdlog::debug("MQTT publish: MQTT v5 publish: mid={0:X} reason-code={1:X}", mid, reason_code); if (nullptr != pClient->m_parentCallbackPublish) { pClient->m_parentCallbackPublish(mosq, pClient->m_pParent, mid); @@ -343,15 +343,15 @@ mqtt_on_message(struct mosquitto *mosq, void *pData, const struct mosquitto_mess vscpClientMqtt *pClient = reinterpret_cast(pData); + std::string payload((const char *) pMsg->payload, pMsg->payloadlen); + spdlog::debug("MQTT CLIENT: MQTT v3 Message trace: Topic = {0} - Payload: {1}", pMsg->topic, payload); + if (nullptr != pClient->m_parentCallbackMessage) { pClient->m_parentCallbackMessage(mosq, pClient->m_pParent, pMsg); } - std::string payload((const char *) pMsg->payload, pMsg->payloadlen); - spdlog::trace("MQTT CLIENT: MQTT v3 Message trace: Topic = {0} - Payload: {1}", pMsg->topic, payload); - if (!pClient->handleMessage(pMsg)) { - spdlog::trace("MQTT CLIENT: MQTT v3 Message parse failure: Topic = {0} - Payload: {1}", pMsg->topic, payload); + spdlog::debug("MQTT CLIENT: MQTT v3 Message parse failure: Topic = {0} - Payload: {1}", pMsg->topic, payload); } } @@ -414,6 +414,7 @@ mqtt_on_subscribe(struct mosquitto *mosq, void *pData, int mid, int qos_count, c } vscpClientMqtt *pClient = reinterpret_cast(pData); + spdlog::debug("MQTT CLIENT: Subscribe v3.11: mid={0} qos_count={1}", mid, qos_count); if (nullptr != pClient->m_parentCallbackSubscribe) { pClient->m_parentCallbackSubscribe(mosq, pClient->m_pParent, mid, qos_count, granted_qos); @@ -448,6 +449,7 @@ mqtt_on_subscribe_v5(struct mosquitto *mosq, } vscpClientMqtt *pClient = reinterpret_cast(pData); + spdlog::debug("MQTT CLIENT: Subscribe v5: mid={0} qos_count={1}", mid, qos_count); if (nullptr != pClient->m_parentCallbackSubscribe) { pClient->m_parentCallbackSubscribe(mosq, pClient->m_pParent, mid, qos_count, granted_qos); @@ -473,6 +475,7 @@ mqtt_on_unsubscribe(struct mosquitto *mosq, void *pData, int mid) } vscpClientMqtt *pClient = reinterpret_cast(pData); + spdlog::debug("MQTT CLIENT: Unsubscribe v3.11: "); if (nullptr != pClient->m_parentCallbackUnsubscribe) { pClient->m_parentCallbackUnsubscribe(mosq, pClient->m_pParent, mid); @@ -498,6 +501,7 @@ mqtt_on_unsubscribe_v5(struct mosquitto *mosq, void *pData, int mid, const mosqu } vscpClientMqtt *pClient = reinterpret_cast(pData); + spdlog::debug("MQTT CLIENT: Unsubscribe v5: "); if (nullptr != pClient->m_parentCallbackUnsubscribe) { pClient->m_parentCallbackUnsubscribe(mosq, pClient->m_pParent, mid); @@ -1391,7 +1395,7 @@ vscpClientMqtt::initFromJson(const std::string &config) ///////////////////////////////////////////////////////////////////////////// // handleMessage // -// Handle incoming message +// Handle incoming (subscribe) message // bool @@ -1413,20 +1417,23 @@ vscpClientMqtt::handleMessage(const struct mosquitto_message *pmsg) return false; } - // We need to find the subscribe channel - if (nullptr != pmsg->topic) { - for (std::list::const_iterator it = m_mqtt_publishTopicList.begin(); - it != m_mqtt_publishTopicList.end(); + // Get subscribe format for subscribe topic + for (std::list::const_iterator it = m_mqtt_subscribeTopicList.begin(); + it != m_mqtt_subscribeTopicList.end(); ++it) { - publishTopic *ppublish = (*it); + subscribeTopic *psubscribe = (*it); // if topics match - if (!strstr(ppublish->getTopic().c_str(), pmsg->topic)) { - format = ppublish->getFormat(); + if (!strstr(psubscribe->getTopic().c_str(), pmsg->topic)) { + format = psubscribe->getFormat(); + break; } } - } - else { + + // If autofmt the payload must be checked to find the correct format + // top convert MQTT msg to VSCP event + if (autofmt == format) { + // Topic is nill we need to find format // If First char of payload... @@ -1460,7 +1467,8 @@ vscpClientMqtt::handleMessage(const struct mosquitto_message *pmsg) } } - // Binary payload will result in zero length string as first character + // Note!!! + // Binary payload will result in zero length string as the first character // is a zero. std::string payload((const char *) pmsg->payload, pmsg->payloadlen); diff --git a/src/vscp/common/vscp_client_socketcan.cpp b/src/vscp/common/vscp_client_socketcan.cpp index b8c9da579..fb6170a1e 100644 --- a/src/vscp/common/vscp_client_socketcan.cpp +++ b/src/vscp/common/vscp_client_socketcan.cpp @@ -566,12 +566,15 @@ vscpClientSocketCan::receive(vscpEvent &ev) return VSCP_ERROR_FIFO_EMPTY; } + pthread_mutex_lock(&m_mutexReceiveQueue); vscpEvent *pev = m_receiveList.front(); if (nullptr == pev) { + pthread_mutex_unlock(&m_mutexReceiveQueue); return VSCP_ERROR_INVALID_POINTER; } vscp_copyEvent(&ev, pev); m_receiveList.pop_front(); + pthread_mutex_unlock(&m_mutexReceiveQueue); vscp_deleteEvent(pev); return VSCP_ERROR_SUCCESS; @@ -608,13 +611,16 @@ vscpClientSocketCan::receive(canalMsg &msg) return VSCP_ERROR_FIFO_EMPTY; } + pthread_mutex_lock(&m_mutexReceiveQueue); vscpEvent *pev = m_receiveList.front(); if (nullptr == pev) { + pthread_mutex_unlock(&m_mutexReceiveQueue); return VSCP_ERROR_INVALID_POINTER; } vscp_convertEventToCanal(&msg, pev, 1); m_receiveList.pop_front(); + pthread_mutex_unlock(&m_mutexReceiveQueue); vscp_deleteEvent(pev); pev = nullptr;