Client for the DeviceHubNet gateway. (You need the gateway SW as well!)
Diff: DeviceHubNet.cpp
- 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