Client for the DeviceHubNet gateway. (You need the gateway SW as well!)
DeviceHubNet.cpp@1:5dca66437dd1, 2017-04-04 (annotated)
- Committer:
- gume
- Date:
- Tue Apr 04 02:21:56 2017 +0000
- Revision:
- 1:5dca66437dd1
- Parent:
- 0:093f1cb20c52
Add documentation to the class
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
gume | 0:093f1cb20c52 | 1 | #include <DeviceHubNet.h> |
gume | 0:093f1cb20c52 | 2 | |
gume | 0:093f1cb20c52 | 3 | int DeviceHubNet::readHex(char *hexStr, uint8_t* hex) |
gume | 0:093f1cb20c52 | 4 | { |
gume | 0:093f1cb20c52 | 5 | |
gume | 0:093f1cb20c52 | 6 | int j = 0; |
gume | 0:093f1cb20c52 | 7 | for (int i = 0; i < strlen(hexStr); i++) { |
gume | 0:093f1cb20c52 | 8 | char c = hexStr[i]; |
gume | 0:093f1cb20c52 | 9 | uint8_t n; |
gume | 0:093f1cb20c52 | 10 | if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) { |
gume | 0:093f1cb20c52 | 11 | if (c <= '9') n = c - '0'; |
gume | 0:093f1cb20c52 | 12 | else if (c <= 'f') n = 10 + c - 'a'; |
gume | 0:093f1cb20c52 | 13 | else if (c <= 'F') n = 10 + c - 'A'; |
gume | 0:093f1cb20c52 | 14 | if (j % 2 == 0) |
gume | 0:093f1cb20c52 | 15 | hex[j/2] = n << 4; |
gume | 0:093f1cb20c52 | 16 | else |
gume | 0:093f1cb20c52 | 17 | hex[j/2] = hex[j/2] + n; |
gume | 0:093f1cb20c52 | 18 | j++; |
gume | 0:093f1cb20c52 | 19 | } |
gume | 0:093f1cb20c52 | 20 | } |
gume | 0:093f1cb20c52 | 21 | |
gume | 0:093f1cb20c52 | 22 | return (j+1)/2; |
gume | 0:093f1cb20c52 | 23 | } |
gume | 0:093f1cb20c52 | 24 | |
gume | 0:093f1cb20c52 | 25 | uint64_t DeviceHubNet::getFullAddress() |
gume | 0:093f1cb20c52 | 26 | { |
gume | 0:093f1cb20c52 | 27 | uint64_t full = 0; |
gume | 0:093f1cb20c52 | 28 | uint32_t netprefix = NETWORK_PREFIX; |
gume | 0:093f1cb20c52 | 29 | memcpy(((char*) &full)+2, (void*) &netprefix, 4); |
gume | 0:093f1cb20c52 | 30 | memcpy(((char*) &full)+0, (void*) &nodeAddress, 2); |
gume | 0:093f1cb20c52 | 31 | return full; |
gume | 0:093f1cb20c52 | 32 | } |
gume | 0:093f1cb20c52 | 33 | |
gume | 0:093f1cb20c52 | 34 | uint64_t DeviceHubNet::getGWAddress() |
gume | 0:093f1cb20c52 | 35 | { |
gume | 0:093f1cb20c52 | 36 | uint64_t full = 0; |
gume | 0:093f1cb20c52 | 37 | uint32_t netprefix = NETWORK_PREFIX; |
gume | 0:093f1cb20c52 | 38 | memcpy(((char*) &full)+2, (void*) &netprefix, 4); |
gume | 0:093f1cb20c52 | 39 | return full; |
gume | 0:093f1cb20c52 | 40 | } |
gume | 0:093f1cb20c52 | 41 | |
gume | 0:093f1cb20c52 | 42 | void DeviceHubNet::registerProject() |
gume | 0:093f1cb20c52 | 43 | { |
gume | 0:093f1cb20c52 | 44 | struct MsgRegister msgRegister; |
gume | 0:093f1cb20c52 | 45 | msgRegister.rType = 1; // Project |
gume | 0:093f1cb20c52 | 46 | memcpy((uint8_t*) msgRegister.id, &projectId, 4); |
gume | 0:093f1cb20c52 | 47 | memcpy((uint8_t*) msgRegister.id + 4, &apiKey, 16); |
gume | 0:093f1cb20c52 | 48 | |
gume | 0:093f1cb20c52 | 49 | sendData(PACKET_REGISTER, (uint8_t*) &msgRegister, 21); |
gume | 0:093f1cb20c52 | 50 | } |
gume | 0:093f1cb20c52 | 51 | |
gume | 0:093f1cb20c52 | 52 | |
gume | 0:093f1cb20c52 | 53 | void DeviceHubNet::registerDevice() |
gume | 0:093f1cb20c52 | 54 | { |
gume | 0:093f1cb20c52 | 55 | struct MsgRegister msgRegister; |
gume | 0:093f1cb20c52 | 56 | msgRegister.rType = 2; // Device |
gume | 0:093f1cb20c52 | 57 | memcpy((uint8_t*) msgRegister.id, &deviceId, 16); |
gume | 0:093f1cb20c52 | 58 | |
gume | 0:093f1cb20c52 | 59 | sendData(PACKET_REGISTER, (uint8_t*) &msgRegister, 17); |
gume | 0:093f1cb20c52 | 60 | } |
gume | 0:093f1cb20c52 | 61 | |
gume | 0:093f1cb20c52 | 62 | |
gume | 0:093f1cb20c52 | 63 | bool DeviceHubNet::sendData(uint8_t type, uint8_t *data, uint8_t len) |
gume | 0:093f1cb20c52 | 64 | { |
gume | 0:093f1cb20c52 | 65 | uint8_t msg[32]; |
gume | 0:093f1cb20c52 | 66 | msg[0] = nodeAddress & 0xff; |
gume | 0:093f1cb20c52 | 67 | msg[1] = nodeAddress >> 8; |
gume | 0:093f1cb20c52 | 68 | msg[2] = type; |
gume | 0:093f1cb20c52 | 69 | msg[3] = msgCounter++; |
gume | 0:093f1cb20c52 | 70 | memcpy(msg + 4, data, len); |
gume | 0:093f1cb20c52 | 71 | |
gume | 0:093f1cb20c52 | 72 | int w = 0; |
gume | 0:093f1cb20c52 | 73 | if (w < 5 && radio->testCarrier()) { |
gume | 0:093f1cb20c52 | 74 | w++; |
gume | 0:093f1cb20c52 | 75 | wait_ms(2); |
gume | 0:093f1cb20c52 | 76 | } |
gume | 0:093f1cb20c52 | 77 | |
gume | 0:093f1cb20c52 | 78 | // Stop listening, send |
gume | 0:093f1cb20c52 | 79 | radio->stopListening(); |
gume | 0:093f1cb20c52 | 80 | radio->setRetries(0, 3); |
gume | 0:093f1cb20c52 | 81 | radio->openWritingPipe(getGWAddress()); |
gume | 0:093f1cb20c52 | 82 | bool ok = radio->write(msg, len +4); |
gume | 0:093f1cb20c52 | 83 | |
gume | 0:093f1cb20c52 | 84 | radio->startListening(); |
gume | 0:093f1cb20c52 | 85 | return ok; |
gume | 0:093f1cb20c52 | 86 | } |
gume | 0:093f1cb20c52 | 87 | |
gume | 0:093f1cb20c52 | 88 | |
gume | 0:093f1cb20c52 | 89 | // public functions |
gume | 0:093f1cb20c52 | 90 | |
gume | 0:093f1cb20c52 | 91 | DeviceHubNet::DeviceHubNet(uint32_t projectId, uint8_t *apiKey, uint8_t *deviceId) |
gume | 0:093f1cb20c52 | 92 | { |
gume | 0:093f1cb20c52 | 93 | this->projectId = projectId; |
gume | 0:093f1cb20c52 | 94 | memcpy(this->apiKey, apiKey, 16); |
gume | 0:093f1cb20c52 | 95 | memcpy(this->deviceId, deviceId, 16); |
gume | 0:093f1cb20c52 | 96 | |
gume | 0:093f1cb20c52 | 97 | nextSId = 1; |
gume | 0:093f1cb20c52 | 98 | } |
gume | 0:093f1cb20c52 | 99 | |
gume | 0:093f1cb20c52 | 100 | DeviceHubNet::DeviceHubNet(uint32_t projectId, char *apiKeyStr, char *deviceIdStr) |
gume | 0:093f1cb20c52 | 101 | { |
gume | 0:093f1cb20c52 | 102 | this->projectId = projectId; |
gume | 0:093f1cb20c52 | 103 | memset(apiKey, 0, 16); |
gume | 0:093f1cb20c52 | 104 | readHex(apiKeyStr, apiKey); |
gume | 0:093f1cb20c52 | 105 | readHex(deviceIdStr, deviceId); |
gume | 0:093f1cb20c52 | 106 | |
gume | 0:093f1cb20c52 | 107 | nextSId = 1; |
gume | 0:093f1cb20c52 | 108 | } |
gume | 0:093f1cb20c52 | 109 | |
gume | 0:093f1cb20c52 | 110 | bool DeviceHubNet::radioPinConfig(PinName mosi, PinName miso, PinName sck, PinName cs, PinName ce) |
gume | 0:093f1cb20c52 | 111 | { |
gume | 0:093f1cb20c52 | 112 | |
gume | 0:093f1cb20c52 | 113 | radio = new RF24(mosi, miso, sck, cs, ce); |
gume | 0:093f1cb20c52 | 114 | return true; |
gume | 0:093f1cb20c52 | 115 | } |
gume | 0:093f1cb20c52 | 116 | |
gume | 0:093f1cb20c52 | 117 | bool DeviceHubNet::radioConfig(uint16_t address, uint8_t channel) |
gume | 0:093f1cb20c52 | 118 | { |
gume | 0:093f1cb20c52 | 119 | nodeAddress = address; |
gume | 0:093f1cb20c52 | 120 | if (!radio) return false; |
gume | 0:093f1cb20c52 | 121 | |
gume | 0:093f1cb20c52 | 122 | radio->begin(); |
gume | 0:093f1cb20c52 | 123 | radio->enableDynamicAck(); |
gume | 0:093f1cb20c52 | 124 | radio->enableDynamicPayloads(); |
gume | 0:093f1cb20c52 | 125 | //radio->openReadingPipe(0, BROADCAST_ADDRESS_LL); |
gume | 0:093f1cb20c52 | 126 | radio->openReadingPipe(1, getFullAddress()); |
gume | 0:093f1cb20c52 | 127 | //radio->setAutoAck(0, false); // Disable autoACK on broadcast |
gume | 0:093f1cb20c52 | 128 | radio->setAutoAck(1, true); // Ensure autoACK is enabled on data/control |
gume | 0:093f1cb20c52 | 129 | |
gume | 0:093f1cb20c52 | 130 | radio->setChannel(channel); |
gume | 0:093f1cb20c52 | 131 | radio->setDataRate(RF24_2MBPS); |
gume | 0:093f1cb20c52 | 132 | radio->setPALevel(RF24_PA_MAX); |
gume | 0:093f1cb20c52 | 133 | |
gume | 0:093f1cb20c52 | 134 | registerProject(); |
gume | 0:093f1cb20c52 | 135 | registerDevice(); |
gume | 0:093f1cb20c52 | 136 | |
gume | 0:093f1cb20c52 | 137 | radio->startListening(); // Start listening |
gume | 0:093f1cb20c52 | 138 | return true; |
gume | 0:093f1cb20c52 | 139 | } |
gume | 0:093f1cb20c52 | 140 | |
gume | 0:093f1cb20c52 | 141 | void DeviceHubNet::radioDump() |
gume | 0:093f1cb20c52 | 142 | { |
gume | 0:093f1cb20c52 | 143 | radio->printDetails(); |
gume | 0:093f1cb20c52 | 144 | } |
gume | 0:093f1cb20c52 | 145 | |
gume | 0:093f1cb20c52 | 146 | void DeviceHubNet::processMsgs() |
gume | 0:093f1cb20c52 | 147 | { |
gume | 0:093f1cb20c52 | 148 | uint8_t packet[32]; |
gume | 0:093f1cb20c52 | 149 | |
gume | 0:093f1cb20c52 | 150 | while (radio->available()) { |
gume | 0:093f1cb20c52 | 151 | uint8_t plen = radio->getDynamicPayloadSize(); |
gume | 0:093f1cb20c52 | 152 | radio->read(packet, plen); |
gume | 0:093f1cb20c52 | 153 | |
gume | 0:093f1cb20c52 | 154 | if (plen < 4) continue; |
gume | 0:093f1cb20c52 | 155 | //printf("New message received. Length: %d\n\r", plen); |
gume | 0:093f1cb20c52 | 156 | //for (int i = 0; i < plen; i++) printf("%02X:", packet[i]); |
gume | 0:093f1cb20c52 | 157 | //printf("\n\r"); |
gume | 0:093f1cb20c52 | 158 | |
gume | 0:093f1cb20c52 | 159 | if (packet[2] == 6) { |
gume | 0:093f1cb20c52 | 160 | // Registration error. Try to re-register everything |
gume | 0:093f1cb20c52 | 161 | registerProject(); |
gume | 0:093f1cb20c52 | 162 | registerDevice(); |
gume | 0:093f1cb20c52 | 163 | |
gume | 0:093f1cb20c52 | 164 | map<uint16_t, string>::iterator it; |
gume | 0:093f1cb20c52 | 165 | for (it = sensors.begin(); it != sensors.end(); ++it) { |
gume | 0:093f1cb20c52 | 166 | reRegisterSensor(it->first); |
gume | 0:093f1cb20c52 | 167 | } |
gume | 0:093f1cb20c52 | 168 | for (it = actuators.begin(); it != actuators.end(); ++it) { |
gume | 0:093f1cb20c52 | 169 | reRegisterActuator(it->first); |
gume | 0:093f1cb20c52 | 170 | } |
gume | 0:093f1cb20c52 | 171 | } |
gume | 0:093f1cb20c52 | 172 | |
gume | 0:093f1cb20c52 | 173 | else if (packet[2] == 3) { |
gume | 0:093f1cb20c52 | 174 | // Data message |
gume | 0:093f1cb20c52 | 175 | uint16_t sid = packet[4] + packet[5] * 256; |
gume | 0:093f1cb20c52 | 176 | uint8_t type = packet[6]; |
gume | 0:093f1cb20c52 | 177 | void (*cb)(uint8_t, uint8_t, float) = (void (*)(uint8_t, uint8_t, float)) actuator_cbs[sid]; |
gume | 0:093f1cb20c52 | 178 | if (type == 0) { |
gume | 0:093f1cb20c52 | 179 | // Digital data |
gume | 0:093f1cb20c52 | 180 | cb(type, packet[7], 0.0); |
gume | 0:093f1cb20c52 | 181 | } else { |
gume | 0:093f1cb20c52 | 182 | // Analog data |
gume | 0:093f1cb20c52 | 183 | float f; |
gume | 0:093f1cb20c52 | 184 | memcpy(&f, packet + 7, 4); |
gume | 0:093f1cb20c52 | 185 | cb(type, 0, f); |
gume | 0:093f1cb20c52 | 186 | } |
gume | 0:093f1cb20c52 | 187 | } |
gume | 0:093f1cb20c52 | 188 | |
gume | 0:093f1cb20c52 | 189 | } |
gume | 0:093f1cb20c52 | 190 | } |
gume | 0:093f1cb20c52 | 191 | |
gume | 0:093f1cb20c52 | 192 | |
gume | 0:093f1cb20c52 | 193 | uint16_t DeviceHubNet::registerSensor(char *sensorName) |
gume | 0:093f1cb20c52 | 194 | { |
gume | 0:093f1cb20c52 | 195 | uint16_t sensorId = nextSId++; |
gume | 0:093f1cb20c52 | 196 | sensors[sensorId] = string(sensorName); |
gume | 0:093f1cb20c52 | 197 | reRegisterSensor(sensorId); |
gume | 0:093f1cb20c52 | 198 | |
gume | 0:093f1cb20c52 | 199 | return sensorId; |
gume | 0:093f1cb20c52 | 200 | } |
gume | 0:093f1cb20c52 | 201 | |
gume | 0:093f1cb20c52 | 202 | uint16_t DeviceHubNet::registerActuator(char *actuatorName, uint8_t type, void (*onReceive)(uint8_t, uint8_t, float)) |
gume | 0:093f1cb20c52 | 203 | { |
gume | 0:093f1cb20c52 | 204 | uint16_t actuatorId = nextSId++; |
gume | 0:093f1cb20c52 | 205 | actuators[actuatorId] = string(actuatorName); |
gume | 0:093f1cb20c52 | 206 | actuator_cbs[actuatorId] = (void*) onReceive; |
gume | 0:093f1cb20c52 | 207 | actuator_types[actuatorId] = type; |
gume | 0:093f1cb20c52 | 208 | reRegisterActuator(actuatorId); |
gume | 0:093f1cb20c52 | 209 | |
gume | 0:093f1cb20c52 | 210 | return actuatorId; |
gume | 0:093f1cb20c52 | 211 | } |
gume | 0:093f1cb20c52 | 212 | |
gume | 0:093f1cb20c52 | 213 | void DeviceHubNet::reRegisterSensor(uint16_t sensorId) |
gume | 0:093f1cb20c52 | 214 | { |
gume | 0:093f1cb20c52 | 215 | char *sensorNameStr = (char*) sensors[sensorId].c_str(); |
gume | 0:093f1cb20c52 | 216 | |
gume | 0:093f1cb20c52 | 217 | struct MsgRegister msgRegister; |
gume | 0:093f1cb20c52 | 218 | msgRegister.rType = 3; // Sensor |
gume | 0:093f1cb20c52 | 219 | msgRegister.id[0] = sensorId & 0xff; |
gume | 0:093f1cb20c52 | 220 | msgRegister.id[1] = sensorId >> 8; |
gume | 0:093f1cb20c52 | 221 | strncpy((char*) msgRegister.id + 2, sensorNameStr, 24); |
gume | 0:093f1cb20c52 | 222 | int l = strlen(sensorNameStr); |
gume | 0:093f1cb20c52 | 223 | if (l > 24) l = 24; |
gume | 0:093f1cb20c52 | 224 | sendData(PACKET_REGISTER, (uint8_t*) &msgRegister, l + 3); |
gume | 0:093f1cb20c52 | 225 | } |
gume | 0:093f1cb20c52 | 226 | |
gume | 0:093f1cb20c52 | 227 | void DeviceHubNet::reRegisterActuator(uint16_t actuatorId) |
gume | 0:093f1cb20c52 | 228 | { |
gume | 0:093f1cb20c52 | 229 | char *actuatorNameStr = (char*) actuators[actuatorId].c_str(); |
gume | 0:093f1cb20c52 | 230 | |
gume | 0:093f1cb20c52 | 231 | struct MsgRegister msgRegister; |
gume | 0:093f1cb20c52 | 232 | msgRegister.rType = 4; // Actuator |
gume | 0:093f1cb20c52 | 233 | msgRegister.id[0] = actuatorId & 0xff; |
gume | 0:093f1cb20c52 | 234 | msgRegister.id[1] = actuatorId >> 8; |
gume | 0:093f1cb20c52 | 235 | msgRegister.id[2] = actuator_types[actuatorId]; |
gume | 0:093f1cb20c52 | 236 | strncpy((char*) msgRegister.id + 3, actuatorNameStr, 24); |
gume | 0:093f1cb20c52 | 237 | int l = strlen(actuatorNameStr); |
gume | 0:093f1cb20c52 | 238 | if (l > 24) l = 24; |
gume | 0:093f1cb20c52 | 239 | sendData(PACKET_REGISTER, (uint8_t*) &msgRegister, l + 4); |
gume | 0:093f1cb20c52 | 240 | } |
gume | 0:093f1cb20c52 | 241 | |
gume | 0:093f1cb20c52 | 242 | bool DeviceHubNet::sendDigitalData(uint16_t sensorId, uint8_t data) |
gume | 0:093f1cb20c52 | 243 | { |
gume | 0:093f1cb20c52 | 244 | struct MsgData msgData; |
gume | 0:093f1cb20c52 | 245 | msgData.sensorId = sensorId; |
gume | 0:093f1cb20c52 | 246 | msgData.dType = 0; |
gume | 0:093f1cb20c52 | 247 | msgData.data.ddata = data; |
gume | 0:093f1cb20c52 | 248 | |
gume | 0:093f1cb20c52 | 249 | return sendData(PACKET_DATA, (uint8_t*) &msgData, 4); |
gume | 0:093f1cb20c52 | 250 | } |
gume | 0:093f1cb20c52 | 251 | |
gume | 0:093f1cb20c52 | 252 | bool DeviceHubNet::sendAnalogData(uint16_t sensorId, float data) |
gume | 0:093f1cb20c52 | 253 | { |
gume | 0:093f1cb20c52 | 254 | struct MsgData msgData; |
gume | 0:093f1cb20c52 | 255 | msgData.sensorId = sensorId; |
gume | 0:093f1cb20c52 | 256 | msgData.dType = 1; |
gume | 0:093f1cb20c52 | 257 | msgData.data.adata = data; |
gume | 0:093f1cb20c52 | 258 | |
gume | 0:093f1cb20c52 | 259 | return sendData(PACKET_DATA, (uint8_t*) &msgData, 7); |
gume | 0:093f1cb20c52 | 260 | } |