Encoding - MDot - Temperature and 2 analog readings

Hi,

I need some help as to how to encode my packet I send, there are most probably some other improvements I can also have in my code (but very new to coding)

I have managed to send the packet as a “String” but want to send in HEX.

Thanks

#include "mbed.h"
#include "DS1820.h"
#include "mDot.h"
#include "MTSLog.h"
#include "MTSText.h"
#include <string>
#include <vector>

using namespace mts;

#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))

// AppEUI
uint8_t AppEUI[8]={ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
// AppKey
uint8_t AppKey[16]={ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

// Some defines for the LoRa configuration
/*
 * EU868 Datarates
 * ---------------
 * DR0 - SF12BW125
 * DR1 - SF11BW125
 * DR2 - SF10BW125
 * DR3 - SF9BW125
 * DR4 - SF8BW125
 * DR5 - SF7BW125
 * DR6 - SF7BW250
 */

#define LORA_SF mDot::DR5
#define LORA_ACK 0
#define LORA_TXPOWER 14

// Ignoring sub band for EU modules.
static uint8_t config_frequency_sub_band = 1;

// DS18B20 OneWire pin
// D2 on Dev Board, pin 13 on mDot
#define DATA_PIN     PC_13

// Temperature sensor object
DS1820 probe(DATA_PIN); //Temprature in

//Capacitive Soil Moisture Sensor V1.2 No1
// A0 on Dev Board, pin 20 on mDot
AnalogIn A1(PB_1); //Analog 1 in for Soil Moisture

//Capacitive Soil  Moisture Sensor V1.2 No2
// A1 on Dev Board, pin 19 on mDot
AnalogIn A2(PB_0); //Analog 2 in for Soil Moisture

// Serial via USB for debugging only
Serial pc(USBTX,USBRX);

int main()
{
    int32_t ret;
    mDot* dot;
    std::vector<uint8_t> send_data;
    std::vector<uint8_t> recv_data;
    std::vector<uint8_t> nwkId;
    std::vector<uint8_t> nwkKey;

    float temperature = 0.0;

    pc.baud(115200);
    pc.printf("TTN OTAA mDot LoRa Temperature sensor\n\r");

    // get a mDot handle
    dot = mDot::getInstance();

//    dot->setLogLevel(MTSLog::WARNING_LEVEL);
    dot->setLogLevel(MTSLog::TRACE_LEVEL);

    logInfo("Checking Config");

    uint8_t *it = AppEUI;
    for (uint8_t i = 0; i<8; i++)
        nwkId.push_back((uint8_t) *it++);
    
    it = AppKey;
    for (uint8_t i = 0; i<16; i++)
        nwkKey.push_back((uint8_t) *it++);

    logInfo("Resetting Config");
    // reset to default config so we know what state we're in
    dot->resetConfig();

    // Set Spreading Factor, higher is lower data rate, smaller packets but longer range
    // Lower is higher data rate, larger packets and shorter range.
    logInfo("Set SF");
    if((ret = dot->setTxDataRate( LORA_SF )) != mDot::MDOT_OK) {
        logError("Failed to set SF %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
    }

    logInfo("Set TxPower");
    if((ret = dot->setTxPower( LORA_TXPOWER )) != mDot::MDOT_OK) {
        logError("Failed to set Tx Power %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
    }

    logInfo("Set Public mode");
    if((ret = dot->setPublicNetwork(true)) != mDot::MDOT_OK) {
        logError("failed to set Public Mode %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
    }

    logInfo("Set AUTO_OTA Join mode");
    if((ret = dot->setJoinMode(mDot::AUTO_OTA)) != mDot::MDOT_OK) {
        logError("Failed to set AUTO_OTA Join Mode %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
    }

    logInfo("Set Ack");
    // 1 retries on Ack, 0 to disable
    if((ret = dot->setAck( LORA_ACK)) != mDot::MDOT_OK) {
        logError("Failed to set Ack %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
    }

    // Library ignores the frequency sub band for 868MHz in EU
    if ((ret = dot->setFrequencySubBand(config_frequency_sub_band)) != mDot::MDOT_OK) {
        logError("Failed to set frequency sub band %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
    }

    logInfo("Set Network Id");
    if ((ret = dot->setNetworkId(nwkId)) != mDot::MDOT_OK) {
        logError("Failed to set Network Id %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
    }
    logInfo("Set Network Key");
    if ((ret = dot->setNetworkKey(nwkKey)) != mDot::MDOT_OK) {
        logError("Failed to set Network Id %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
    }

    logInfo("Saving Config");
    // Save config
    if (! dot->saveConfig()) {
        logError("failed to save configuration");
    }

    pc.printf("Device ID {");
    std::vector<uint8_t> deviceId;
    deviceId = dot->getDeviceId();
    for (std::vector<uint8_t>::iterator it = deviceId.begin() ; it != deviceId.end(); ++it) {
        pc.printf("0x%2.2X",*it );
        pc.printf("%s", it != (deviceId.end() -1 ) ? ", " : " " );
    }
    pc.printf("}\r\n");

    std::vector<uint8_t> netId;
    pc.printf("Network Id/App EUI {");
    netId = dot->getNetworkId();
    for (std::vector<uint8_t>::iterator it = netId.begin() ; it != netId.end(); ++it) {
        pc.printf("0x%2.2X", *it );
        pc.printf("%s", it != (netId.end() -1 ) ? ", " : " " );
    }
    pc.printf("}\r\n");

    std::vector<uint8_t> netKey;
    pc.printf("Network Key/App Key {");
    netKey = dot->getNetworkKey();
    for (std::vector<uint8_t>::iterator it = netKey.begin() ; it != netKey.end(); ++it) {
        pc.printf("0x%2.2X", *it );
        pc.printf("%s", it != (netKey.end() -1 ) ? ", " : " " );
    }
    pc.printf("}\r\n");

    // Display LoRa parameters
    // Display label and values in different colours, show pretty values not numeric values where applicable
/*
    pc.printf("Public Network: %s\r\n", (char*)(dot->getPublicNetwork() ? "Yes" : "No") );
    pc.printf("Frequency: %s\r\n", (char*)mDot::FrequencyBandStr(dot->getFrequencyBand()).c_str() );
    pc.printf("Sub Band: %s\r\n", (char*)mDot::FrequencySubBandStr(dot->getFrequencySubBand()).c_str() );
    pc.printf("Join Mode: %s\r\n", (char*)mDot::JoinModeStr(dot->getJoinMode()).c_str() );
    pc.printf("Join Retries: %d\r\n", dot->getJoinRetries() );
    pc.printf("Join Byte Order: %s\r\n", (char*)(dot->getJoinByteOrder() == 0 ? "LSB" : "MSB") );
    pc.printf("Link Check Count: %d\r\n", dot->getLinkCheckCount() );
    pc.printf("Link Check Thold: %d\r\n", dot->getLinkCheckThreshold() );
    pc.printf("Tx Data Rate: %s\r\n", (char*)mDot::DataRateStr(dot->getTxDataRate()).c_str() );
    pc.printf("Tx Power: %d\r\n", dot->getTxPower() );
    pc.printf("TxWait: %s, ", (dot->getTxWait() ? "Y" : "N" ));
    pc.printf("CRC: %s, ", (dot->getCrc() ? "Y" : "N") );
    pc.printf("Ack: %s\r\n", (dot->getAck() ? "Y" : "N")  );
*/
    logInfo("Joining Network");

    while ((ret = dot->joinNetwork()) != mDot::MDOT_OK) {
        logError("failed to join network [%d][%s]", ret, mDot::getReturnCodeString(ret).c_str());
        wait_ms(dot->getNextTxMs() + 1);
    }

    logInfo("Joined Network");

    // Display Network session key and data session key from Join command
/*
    std::vector<uint8_t> tmp = dot->getNetworkSessionKey();
    pc.printf("Network Session Key: ");
    pc.printf("%s\r\n", mts::Text::bin2hexString(tmp, " ").c_str());

    tmp = dot->getDataSessionKey();
    pc.printf("Data Session Key: ");
    pc.printf("%s\r\n", mts::Text::bin2hexString(tmp, " ").c_str());
*/
    // Set the Temperature sesnor resolution, 9 bits is enough and makes it faster to provide a reading.
    probe.setResolution(9);

    char dataBuf[50];
    while( 1 ) {

            float analog1; //Analog 1 in for Soil Moisture No.1
            analog1 = A1.read() * 3.3;

            float analog2; //Analog 2 in for Soil Moisture No.2
            analog2 = A2.read() * 3.3;

            //Start temperature conversion, wait until ready
        probe.convertTemperature(true, DS1820::all_devices);
            // Output data as JSON e.g. {"t":21.3}
        temperature = probe.temperature();

        //sprintf(dataBuf, "%3.1f", temperature );
        sprintf(dataBuf, "%3.1f,%3.1f,%04.2f", temperature , analog1 , analog2 );
        pc.printf("%s\n",dataBuf);
            send_data.clear();
            // probably not the most efficent way to do this
            for( int i=0; i< strlen(dataBuf); i++ )
                send_data.push_back( dataBuf[i] );

            if ((ret = dot->send(send_data)) != mDot::MDOT_OK) {
                logError("failed to send: [%d][%s]", ret, mDot::getReturnCodeString(ret).c_str());
            } else {
                logInfo("send data: %s", Text::bin2hexString(send_data).c_str());
            }

           // Should  sleep here and wakeup after a set 10 minute interval.
            // in the 868 (EU) frequency band, we need to wait until another channel is available before transmitting again
            uint32_t sleep_time = std::max((uint32_t)600000, (uint32_t)dot->getNextTxMs()) / 1000;

            // go to sleep and wake up automatically sleep_time seconds later
            dot->sleep(sleep_time, mDot::RTC_ALARM);
    }

}

Moderator edit to remove keys and link that may reveal keys.

It’s supper time, so I can get you going quickly with an copynpasta from an answer I’ve just given on the RAK forum on exactly this topic. Please note, this was for an Arduino user so a small amount of translation will be required, but as an mbed user I’m confident you’ll cope :wink:

#define PAYLOAD_SIZE  6

int data[PAYLOAD_SIZE]; //  binary data structure with enough bytes for the payload

int temperature = 20;
int humidity = 35;
int pressure = 935;

/* This is where you get your readings
// Get your readings
temperature = getTheTemperature();
humidity = getTheHumidity();
pressure = getThePressure();
*/

// Transfer to the binary data structure
data[0] = highByte(temperature);
data[1] = lowByte(temperature);
data[2] = highByte(humidity);
data[3] = lowByte(humidity);
data[4] = highByte(pressure);
data[5] = lowByte(pressure);

highByte and lowByte are substitutes for bit masks & shifting - I’d give examples but I’ve just been cornered on the cooking front.

1 Like

Hi,

Thanks for your help.

I am 100% on my way now.

1 Like