int main(int argc, char* argv[]) { if (argc != 2) uso(); if (strcmp(argv[1], "-r") == 0 ) { mode = receiver; NODE_ID = RECEIVER_ID; GATEWAY_ID = SENDER_ID; // not really needed... } else if (strcmp(argv[1], "-s") == 0) { mode = sender; NODE_ID = SENDER_ID; GATEWAY_ID = RECEIVER_ID; } else { fprintf(stderr, "invalid arguments"); uso(); } //RFM69 --------------------------- theConfig.networkId = NETWORK_ID; theConfig.nodeId = NODE_ID; theConfig.frequency = RFM_FREQUENCY; theConfig.keyLength = 16; memcpy(theConfig.key, ENCRYPTION_KEY, 16); theConfig.isRFM69HW = RFM69H; theConfig.promiscuousMode = true; LOG("NETWORK %d NODE_ID %d FREQUENCY %d\n", theConfig.networkId, theConfig.nodeId, theConfig.frequency); rfm69 = new RFM69(); rfm69->initialize(theConfig.frequency,theConfig.nodeId,theConfig.networkId); initRfm(rfm69); LOG("setup complete\n"); return run_loop(); }
/* Loop until it is explicitly halted or the network is lost, then clean up. */ static int run_loop(struct mosquitto *m) { int res; long lastMess; for (;;) { res = mosquitto_loop(m, 10, 1); // No messages have been received withing MESSAGE_WATCHDOG interval if (millis() > lastMess + theConfig.messageWatchdogDelay) { LOG("=== Message WatchDog ===\n"); theStats.messageWatchdog++; // re-initialise the radio initRfm(rfm69); // reset watchdog lastMess = millis(); } if (rfm69->receiveDone()) { // record last message received time - to compute radio watchdog lastMess = millis(); theStats.messageReceived++; // store the received data localy, so they can be overwited // This will allow to send ACK immediately after uint8_t data[RF69_MAX_DATA_LEN]; // recv/xmit buf, including header & crc bytes uint8_t dataLength = rfm69->DATALEN; memcpy(data, (void *)rfm69->DATA, dataLength); uint8_t theNodeID = rfm69->SENDERID; uint8_t targetID = rfm69->TARGETID; // should match _address uint8_t PAYLOADLEN = rfm69->PAYLOADLEN; uint8_t ACK_REQUESTED = rfm69->ACK_REQUESTED; uint8_t ACK_RECEIVED = rfm69->ACK_RECEIVED; // should be polled immediately after sending a packet with ACK request int16_t RSSI = rfm69->RSSI; // most accurate RSSI during reception (closest to the reception) if (ACK_REQUESTED && targetID == theConfig.nodeId) { // When a node requests an ACK, respond to the ACK // but only if the Node ID is correct theStats.ackRequested++; rfm69->sendACK(); if (theStats.ackCount++%3==0) { // and also send a packet requesting an ACK (every 3rd one only) // This way both TX/RX NODE functions are tested on 1 end at the GATEWAY usleep(3000); //need this when sending right after reception .. ? theStats.messageSent++; if (rfm69->sendWithRetry(theNodeID, "ACK TEST", 8)) { // 3 retry, over 200ms delay each theStats.ackReceived++; LOG("Pinging node %d - ACK - ok!", theNodeID); } else { theStats.ackMissed++; LOG("Pinging node %d - ACK - nothing!", theNodeID); } } }//end if radio.ACK_REQESTED LOG("[%d] to [%d] ", theNodeID, targetID); if (dataLength != sizeof(Payload)) { LOG("Invalid payload received, not matching Payload struct! %d - %d\r\n", dataLength, sizeof(Payload)); hexDump(NULL, data, dataLength, 16); } else { theData = *(Payload*)data; //assume radio.DATA actually contains our struct and not something else //save it for mosquitto: sensorNode.nodeID = theData.nodeID; sensorNode.sensorID = theData.sensorID; sensorNode.var1_usl = theData.var1_usl; sensorNode.var2_float = theData.var2_float; sensorNode.var3_float = theData.var3_float; sensorNode.var4_int = RSSI; LOG("Received Node ID = %d Device ID = %d Time = %d RSSI = %d var2 = %f var3 = %f\n", sensorNode.nodeID, sensorNode.sensorID, sensorNode.var1_usl, sensorNode.var4_int, sensorNode.var2_float, sensorNode.var3_float ); if (sensorNode.nodeID == theNodeID) sendMQTT = 1; else { hexDump(NULL, data, dataLength, 16); } } } //end if radio.receive if (sendMQTT == 1) { //send var1_usl MQTTSendULong(m, sensorNode.nodeID, sensorNode.sensorID, 1, sensorNode.var1_usl); //send var2_float MQTTSendFloat(m, sensorNode.nodeID, sensorNode.sensorID, 2, sensorNode.var2_float); //send var3_float MQTTSendFloat(m, sensorNode.nodeID, sensorNode.sensorID, 3, sensorNode.var3_float); //send var4_int, RSSI MQTTSendInt(m, sensorNode.nodeID, sensorNode.sensorID, 4, sensorNode.var4_int); sendMQTT = 0; }//end if sendMQTT } mosquitto_destroy(m); (void)mosquitto_lib_cleanup(); if (res == MOSQ_ERR_SUCCESS) { return 0; } else { return 1; } }
int main(int argc, char* argv[]) { if (argc != 1) uso(); #ifdef DAEMON //Adapted from http://www.netzmafia.de/skripten/unix/linux-daemon-howto.html pid_t pid, sid; openlog("Gatewayd", LOG_PID, LOG_USER); pid = fork(); if (pid < 0) { LOG_E("fork failed"); exit(EXIT_FAILURE); } /* If we got a good PID, then we can exit the parent process. */ if (pid > 0) { LOG("Child spawned, pid %d\n", pid); exit(EXIT_SUCCESS); } /* Change the file mode mask */ umask(0); /* Create a new SID for the child process */ sid = setsid(); if (sid < 0) { LOG_E("setsid failed"); exit(EXIT_FAILURE); } /* Change the current working directory */ if ((chdir("/")) < 0) { LOG_E("chdir failed"); exit(EXIT_FAILURE); } /* Close out the standard file descriptors */ close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); #endif //DAEMON // Mosquitto ---------------------- struct mosquitto *m = mosquitto_new(MQTT_CLIENT_ID, true, null); if (m == NULL) { die("init() failure\n"); } if (!set_callbacks(m)) { die("set_callbacks() failure\n"); } if (!connect(m)) { die("connect() failure\n"); } //RFM69 --------------------------- theConfig.networkId = 101; theConfig.nodeId = 12; theConfig.frequency = RF69_868MHZ; theConfig.keyLength = 16; memcpy(theConfig.key, "pecmosg110028225", 16); theConfig.isRFM69HW = true; theConfig.promiscuousMode = true; theConfig.messageWatchdogDelay = 1800000; // 1800 seconds (30 minutes) between two messages rfm69 = new RFM69(); rfm69->initialize(theConfig.frequency,theConfig.nodeId,theConfig.networkId); initRfm(rfm69); // Mosquitto subscription --------- char subsciptionMask[128]; sprintf(subsciptionMask, "%s/%03d/#", MQTT_ROOT, theConfig.networkId); LOG("Subscribe to Mosquitto topic: %s\n", subsciptionMask); mosquitto_subscribe(m, NULL, subsciptionMask, 0); LOG("setup complete\n"); return run_loop(m); } // end of setup