Client for the DeviceHubNet gateway. (You need the gateway SW as well!)

Dependents:   DeviceHubNet_DEMO

DeviceHubNet.cpp

Committer:
gume
Date:
2017-03-28
Revision:
0:093f1cb20c52

File content as of revision 0:093f1cb20c52:

#include <DeviceHubNet.h>

int DeviceHubNet::readHex(char *hexStr, uint8_t* hex)
{

    int j = 0;
    for (int i = 0; i < strlen(hexStr); i++) {
        char c = hexStr[i];
        uint8_t n;
        if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) {
            if (c <= '9') n = c - '0';
            else if (c <= 'f') n = 10 + c - 'a';
            else if (c <= 'F') n = 10 + c - 'A';
            if (j % 2 == 0)
                hex[j/2] = n << 4;
            else
                hex[j/2] = hex[j/2] + n;
            j++;
        }
    }

    return (j+1)/2;
}

uint64_t DeviceHubNet::getFullAddress()
{
    uint64_t full = 0;
    uint32_t netprefix = NETWORK_PREFIX;
    memcpy(((char*) &full)+2, (void*) &netprefix, 4);
    memcpy(((char*) &full)+0, (void*) &nodeAddress, 2);
    return full;
}

uint64_t DeviceHubNet::getGWAddress()
{
    uint64_t full = 0;
    uint32_t netprefix = NETWORK_PREFIX;
    memcpy(((char*) &full)+2, (void*) &netprefix, 4);
    return full;
}

void DeviceHubNet::registerProject()
{
    struct MsgRegister msgRegister;
    msgRegister.rType = 1; // Project
    memcpy((uint8_t*) msgRegister.id, &projectId, 4);
    memcpy((uint8_t*) msgRegister.id + 4, &apiKey, 16);

    sendData(PACKET_REGISTER, (uint8_t*) &msgRegister, 21);
}


void DeviceHubNet::registerDevice()
{
    struct MsgRegister msgRegister;
    msgRegister.rType = 2; // Device
    memcpy((uint8_t*) msgRegister.id, &deviceId, 16);

    sendData(PACKET_REGISTER, (uint8_t*) &msgRegister, 17);
}


bool DeviceHubNet::sendData(uint8_t type, uint8_t *data, uint8_t len)
{
    uint8_t msg[32];
    msg[0] = nodeAddress & 0xff;
    msg[1] = nodeAddress >> 8;
    msg[2] = type;
    msg[3] = msgCounter++;
    memcpy(msg + 4, data, len);

    int w = 0;
    if (w < 5 && radio->testCarrier()) {
        w++;
        wait_ms(2);
    }

    // Stop listening, send
    radio->stopListening();
    radio->setRetries(0, 3);
    radio->openWritingPipe(getGWAddress());
    bool ok = radio->write(msg, len  +4);

    radio->startListening();
    return ok;
}


// public functions

DeviceHubNet::DeviceHubNet(uint32_t projectId, uint8_t *apiKey, uint8_t *deviceId)
{
    this->projectId = projectId;
    memcpy(this->apiKey, apiKey, 16);
    memcpy(this->deviceId, deviceId, 16);

    nextSId = 1;
}

DeviceHubNet::DeviceHubNet(uint32_t projectId, char *apiKeyStr, char *deviceIdStr)
{
    this->projectId = projectId;
    memset(apiKey, 0, 16);
    readHex(apiKeyStr, apiKey);
    readHex(deviceIdStr, deviceId);

    nextSId = 1;
}

bool DeviceHubNet::radioPinConfig(PinName mosi, PinName miso, PinName sck, PinName cs, PinName ce)
{

    radio = new RF24(mosi, miso, sck, cs, ce);
    return true;
}

bool DeviceHubNet::radioConfig(uint16_t address, uint8_t channel)
{
    nodeAddress = address;
    if (!radio) return false;

    radio->begin();
    radio->enableDynamicAck();
    radio->enableDynamicPayloads();
    //radio->openReadingPipe(0, BROADCAST_ADDRESS_LL);
    radio->openReadingPipe(1, getFullAddress());
    //radio->setAutoAck(0, false);   // Disable autoACK on broadcast
    radio->setAutoAck(1, true);    // Ensure autoACK is enabled on data/control

    radio->setChannel(channel);
    radio->setDataRate(RF24_2MBPS);
    radio->setPALevel(RF24_PA_MAX);

    registerProject();
    registerDevice();

    radio->startListening();        // Start listening
    return true;
}

void DeviceHubNet::radioDump()
{
    radio->printDetails();
}

void DeviceHubNet::processMsgs()
{
    uint8_t packet[32];

    while (radio->available())  {
        uint8_t plen = radio->getDynamicPayloadSize();
        radio->read(packet, plen);

        if (plen < 4) continue;
        //printf("New message received. Length: %d\n\r", plen);
        //for (int i = 0; i < plen; i++) printf("%02X:", packet[i]);
        //printf("\n\r");

        if (packet[2] == 6) {
            // Registration error. Try to re-register everything
            registerProject();
            registerDevice();

            map<uint16_t, string>::iterator it;
            for (it = sensors.begin(); it != sensors.end(); ++it) {
                reRegisterSensor(it->first);
            }
            for (it = actuators.begin(); it != actuators.end(); ++it) {
                reRegisterActuator(it->first);
            }
        }
        
        else if (packet[2] == 3) {
            // Data message
            uint16_t sid = packet[4] + packet[5] * 256;
            uint8_t type = packet[6];
            void (*cb)(uint8_t, uint8_t, float) = (void (*)(uint8_t, uint8_t, float)) actuator_cbs[sid];
            if (type == 0) {
                // Digital data
                cb(type, packet[7], 0.0);
            } else {
                // Analog data
                float f;
                memcpy(&f, packet + 7, 4);
                cb(type, 0, f);
            }
        }
        
    }
}


uint16_t DeviceHubNet::registerSensor(char *sensorName)
{
    uint16_t sensorId = nextSId++;
    sensors[sensorId] = string(sensorName);
    reRegisterSensor(sensorId);
    
    return sensorId;
}

uint16_t DeviceHubNet::registerActuator(char *actuatorName, uint8_t type, void (*onReceive)(uint8_t, uint8_t, float))
{
    uint16_t actuatorId = nextSId++;
    actuators[actuatorId] = string(actuatorName);    
    actuator_cbs[actuatorId] = (void*) onReceive;
    actuator_types[actuatorId] = type;
    reRegisterActuator(actuatorId);
    
    return actuatorId;
}

void DeviceHubNet::reRegisterSensor(uint16_t sensorId)
{
    char *sensorNameStr = (char*) sensors[sensorId].c_str();
    
    struct MsgRegister msgRegister;
    msgRegister.rType = 3; // Sensor
    msgRegister.id[0] = sensorId & 0xff;
    msgRegister.id[1] = sensorId >> 8;
    strncpy((char*) msgRegister.id + 2, sensorNameStr, 24);
    int l = strlen(sensorNameStr);
    if (l > 24) l = 24;
    sendData(PACKET_REGISTER, (uint8_t*) &msgRegister, l + 3);
}

void DeviceHubNet::reRegisterActuator(uint16_t actuatorId)
{
    char *actuatorNameStr = (char*) actuators[actuatorId].c_str();
    
    struct MsgRegister msgRegister;
    msgRegister.rType = 4; // Actuator
    msgRegister.id[0] = actuatorId & 0xff;
    msgRegister.id[1] = actuatorId >> 8;
    msgRegister.id[2] = actuator_types[actuatorId];
    strncpy((char*) msgRegister.id + 3, actuatorNameStr, 24);
    int l = strlen(actuatorNameStr);
    if (l > 24) l = 24;
    sendData(PACKET_REGISTER, (uint8_t*) &msgRegister, l + 4);
}

bool DeviceHubNet::sendDigitalData(uint16_t sensorId, uint8_t data)
{
    struct MsgData msgData;
    msgData.sensorId = sensorId;
    msgData.dType = 0;
    msgData.data.ddata = data;

    return sendData(PACKET_DATA, (uint8_t*) &msgData, 4);
}

bool DeviceHubNet::sendAnalogData(uint16_t sensorId, float data)
{
    struct MsgData msgData;
    msgData.sensorId = sensorId;
    msgData.dType = 1;
    msgData.data.adata = data;

    return sendData(PACKET_DATA, (uint8_t*) &msgData, 7);
}