|
- // vim: noai:sw=2:tw=88
-
- #include "NoiseSensor.h"
- #include "time.h"
- #include <ESP32Time.h>
- #include <TimeLib.h>
-
- ESP32Time t;
-
- bool NoiseSensorClass::begin() {
- _PACKET_SIZE = ( _tick_count + LORA_HEADER_LENGTH + BATTERY_FIELD_SIZE );
- _REQUEST_SIZE = ( PACKET_COUNT * _PACKET_SIZE * 2 ); // * 2, it's 16 bit.
-
- for (int i = 0; i < PACKET_COUNT; i++) {
- _nodes[i] = new NoiseSensorNode(i, _PACKET_SIZE * 2);
- }
-
- if (this->_tick_duration < 2) {
- Serial.println("--> Using a tick duration of less than two seconds. This "
- "will fail unless you've increased the MCUs SYSCLK!");
- }
-
- if (this->_tick_count >= 100) {
- Serial.println(
- "--> Using a tick count of more than 100 gets dangerously close to the "
- "LoRa transmission limitations and is not supported as of now.");
- }
-
-
- if (!setupNTPClient()) {
- Serial.println("!!!-------------------------!!!");
- Serial.println("NTPClient couldn't be started.");
- Serial.println("!!!-------------------------!!!");
- return false;
- }
-
- Wire.begin(21, 22, 400000);
- sendSyncBeacon();
- this->_first_sync = 1;
- }
-
- bool NoiseSensorClass::begin(uint8_t tick_count) {
- this->_tick_count = tick_count;
- this->begin();
- }
-
- bool NoiseSensorClass::begin(uint8_t tick_count, uint8_t tick_duration) {
- this->_tick_count = tick_count;
- this->_tick_duration = tick_duration;
- this->begin();
- }
-
- bool NoiseSensorClass::begin(uint8_t tick_count, uint8_t tick_duration,
- uint8_t tx_offset) {
- this->_tick_count = tick_count;
- this->_tick_duration = tick_duration;
- this->_tx_offset = tx_offset;
- this->begin();
- }
-
- void NoiseSensorClass::setIds(const char* sensebox_ids[], const char* sensor_ids[]) {
- for (int i = 0; i < PACKET_COUNT; i++) {
- char tmp[24] = {0};
- _nodes[i]->sensebox_id = sensebox_ids[i];
- _nodes[i]->sensor_id = sensor_ids[i];
- }
- }
-
-
- bool NoiseSensorClass::beaconReady() {
- if (t.getEpoch() - _last_sync_time ==
- (this->_tick_count * this->_tick_duration)) {
- Serial.println("---->Beacon ready");
- return true;
- }
- return false;
- }
-
- bool NoiseSensorClass::requestReady() {
- // 1 second as tolerance
- if (!this->_first_sync &&
- t.getEpoch() - _last_sync_time ==
- (5 * this->_tx_offset * this->_tick_duration + 1)) {
- Serial.println("---->Request ready");
- return true;
- }
- return false;
- }
-
- bool NoiseSensorClass::read() {
- for (int pkt = 0; pkt < PACKET_COUNT; pkt++) {
- NoiseSensorNode* node = _nodes[pkt];
- // Calculate the time of the sync message that triggered this packet.
- uint32_t time_offset = (_tick_count * _tick_duration); // TODO Move
- node->_sync_message_ts = this->_last_sync_time - time_offset;
- /*
- Serial.print("Last sync time: ");
- Serial.println(_last_sync_time);
- Serial.print("Offset: ");
- Serial.println(time_offset);
- Serial.print("TS: ");
- Serial.println(_nodes[pkt]->_sync_message_ts);
- Serial.print(minute(_nodes[pkt]->_sync_message_ts));
- Serial.print(":");
- Serial.println(second(_nodes[pkt]->_sync_message_ts));
- */
- /*
- if (node->missing_answers > 0) {
- node->_sync_message_ts -= time_offset * node->missing_answers;
- }
- */
- Wire.requestFrom(_i2c_address, _PACKET_SIZE * 2);
- char req_buf[_PACKET_SIZE * 2] = {0};
- uint8_t count = 0;
-
- while (Wire.available()) {
- char c = Wire.read();
- req_buf[count] = c;
- count++;
- }
-
- // TODO There's probably a neater way than doing these low level operations.
- for (int i = 0; i < _PACKET_SIZE * 2; i+=2) {
- uint16_t n = req_buf[i+1] << 8;
- n |= req_buf[i];
- node->_measurements[i/2] = n;
- Serial.print(n);
- Serial.print(" ");
- }
-
- Serial.println();
- }
-
- // Skip 0, it has no battery.
- for (int pkt = 1; pkt < PACKET_COUNT; pkt++) {
- // TODO Move this to a sane place (own function).
- if (_nodes[pkt]->_measurements[_PACKET_SIZE - 1]) {
- Serial.print("Battery low on device");
- Serial.println(pkt);
- }
- }
-
- Serial.println("Reading done.");
- return true;
- }
-
- void NoiseSensorClass::printMeasurements(uint8_t node_id) {
- uint32_t ts = this->_nodes[node_id]->_sync_message_ts;
- char printbuf[32];
- sprintf(printbuf, "- ID %u - ", node_id);
- Serial.println(printbuf);
-
- for (int i = 2; i < (this->_PACKET_SIZE - BATTERY_FIELD_SIZE); i++) {
- // TODO Timestamps
-
- Serial.println(this->_nodes[node_id]->_measurements[i]);
- ts += this->_tick_duration;
- }
- }
-
- bool NoiseSensorClass::sendSyncBeacon() {
- uint8_t setup_values[4];
-
- setup_values[0] = 1;
- setup_values[1] = this->_tick_count;
- setup_values[2] = this->_tick_duration;
- setup_values[3] = this->_tx_offset;
-
- Serial.println("Sent beacon");
-
- Wire.beginTransmission(_i2c_address);
- Wire.write((uint8_t *) setup_values, sizeof(setup_values));
- Wire.endTransmission();
-
- this->_first_sync = 0;
- _last_sync_time = t.getEpoch();
- Serial.println(_last_sync_time);
-
- }
-
- String NoiseSensorClass::buildSenseBoxJSON(uint8_t device_id) {
- NoiseSensorNode* node = _nodes[device_id];
- uint32_t ts = node->_sync_message_ts;
-
- // Each measurement line is max. 94 chars long + 2 curly brackets.
- uint16_t bufsize = _tick_count * 94 + 2;
- char json_buf[bufsize] = {0};
- char sensor_id[25] = {0};
- node->sensor_id.toCharArray(sensor_id, 25);
-
- // Build a json string in a very comprehensible way...
- strcat(json_buf, "[\n");
-
- for (int i = 2; i < (_PACKET_SIZE - BATTERY_FIELD_SIZE); i++) {
- char tmpbuf[1024] = {0};
- char timestamp[24] = {0};
- float m = node->_measurements[i] / 10.0; // From fixed point to float.
-
- if (m >= 29 && m <= 120) {
- sprintf(timestamp, "%i-%02i-%02iT%02i:%02i:%02iZ", year(ts), month(ts),
- day(ts), hour(ts), minute(ts), second(ts));
-
- sprintf(tmpbuf, "{\"sensor\":\"%s\", \"value\":\"%.1f\", \"createdAt\":\"%s\"}", sensor_id, m, timestamp);
-
- // No trailing comma on the last entry.
- if (i != _PACKET_SIZE - BATTERY_FIELD_SIZE - 1) {
- strcat(tmpbuf, ",");
- }
- strcat(json_buf, tmpbuf);
- strcat(json_buf, "\n");
- }
-
- ts += this->_tick_duration;
- }
-
-
- /*
- if (strlen(json_buf) > 2) {
- node->missing_answers = 0;
- Serial.println("Missing answers reset.");
- } else {
- node->missing_answers++;
- Serial.print("Missing answers: ");
- Serial.println(node->missing_answers);
- }
- */
-
- strcat(json_buf, "]");
-
- return json_buf;
- }
-
- String NoiseSensorClass::buildHTTPHeader(uint8_t device_id, const char* server, uint16_t content_length) {
- char sb_id[25] = {0};
- _nodes[device_id]->sensebox_id.toCharArray(sb_id, 25);
-
- char uploadbuf[2048] = {0};
- sprintf(uploadbuf, "POST /boxes/%s/data HTTP/1.1\n"
- "Host: %s\n"
- "content-type: application/json\n"
- "Connection: close\n"
- "Content-Length: %u", sb_id, server, content_length);
-
- return String(uploadbuf);
- }
-
- // Private functions
-
- bool NoiseSensorClass::setupNTPClient() {
- configTime(0, 0, "de.pool.ntp.org");
-
- // Allow processing of the package.
- delay(1000);
-
- struct tm timeinfo;
- if(!getLocalTime(&timeinfo)){
- Serial.println("Failed to obtain time");
- return false;
- }
- char timestamp[24];
- uint32_t ts = t.getEpoch();
- sprintf(timestamp, "%i-%02i-%02iT%02i:%02i:%02iZ", year(ts), month(ts),
- day(ts), hour(ts), minute(ts), second(ts));
- Serial.println(timestamp);
- return true;
- }
-
- NoiseSensorClass NoiseSensor;
|