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

Dependents:   DeviceHubNet_DEMO

Revision:
0:093f1cb20c52
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DeviceHubNet.cpp	Tue Mar 28 01:33:39 2017 +0000
@@ -0,0 +1,260 @@
+#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);
+}
\ No newline at end of file