Ejemplo n.º 1
0
Meter::Meter(std::list<Option> pOptions) :
		_name("meter")
{
	id = instances++;
	OptionList optlist;

	// set meter name
	std::stringstream oss;
	oss<<"mtr"<< id;
	_name = oss.str();

	//optlist.dump(pOptions);

	try {
		// protocol
		const char *protocol_str = optlist.lookup_string(pOptions, "protocol");
		print(log_debug, "Creating new meter with protocol %s.", name(), protocol_str);

		if (meter_lookup_protocol(protocol_str, &_protocol_id) != SUCCESS) {
//print(log_error, "Invalid protocol: %s", mtr, protocol_str);
//return ERR; /* skipping this meter */
			throw vz::VZException("Protocol not found.");
		}
	} catch (vz::VZException &e) {
		std::stringstream oss;
		oss << e.what();
		print(log_error, "Missing protocol or invalid type (%s)", name(), oss.str().c_str());
		throw;
	}

	try {
		// interval
		Option interval_opt = optlist.lookup(pOptions, "interval");
		_interval = (int)(interval_opt);
	} catch (vz::OptionNotFoundException &e) {
		_interval = -1; /* indicates unknown interval */
	} catch (vz::VZException &e) {
		print(log_error, "Invalid type for interval", name());
		throw;
	}
	try {
		// aggregation time
		Option interval_opt = optlist.lookup(pOptions, "aggtime");
		_aggtime = (int)(interval_opt);
	} catch (vz::OptionNotFoundException &e) {
		_aggtime = -1; /* indicates no aggregation */
	} catch (vz::VZException &e) {
		print(log_error, "Invalid type for aggtime", name());
		throw;
	}
	try {
		_aggFixedInterval = optlist.lookup_bool(pOptions, "aggfixedinterval");
	} catch (vz::OptionNotFoundException &e) {
		_aggFixedInterval = false;
	} catch (vz::VZException &e) {
		print(log_error, "Invalid type for aggfixedinterval", name());
		throw;
	}

	try{
		const meter_details_t *details = meter_get_details(_protocol_id);
		if (details->periodic == true && _interval < 0) {
			print(log_error, "Interval has to be set and positive!", name());
		}
	} catch (vz::VZException &e) {
		std::stringstream oss;
		oss << e.what();
		print(log_error, "Missing protocol or invalid type (%s)", name(), oss.str().c_str());
		throw;
	}
	switch(_protocol_id) {
		case meter_protocol_file:
			_protocol = vz::protocol::Protocol::Ptr(new MeterFile(pOptions));
			_identifier = ReadingIdentifier::Ptr(new StringIdentifier());
			break;
		case meter_protocol_exec:
			_protocol = vz::protocol::Protocol::Ptr(new MeterExec(pOptions));
			_identifier = ReadingIdentifier::Ptr(new StringIdentifier());
			break;
		case meter_protocol_random:
			_protocol = vz::protocol::Protocol::Ptr(new MeterRandom(pOptions));
			_identifier = ReadingIdentifier::Ptr(new NilIdentifier());
			break;
		case meter_protocol_s0:
			_protocol = vz::protocol::Protocol::Ptr(new MeterS0(pOptions));
			_identifier = ReadingIdentifier::Ptr(new StringIdentifier());
			break;
		case meter_protocol_d0:
			_protocol = vz::protocol::Protocol::Ptr(new MeterD0(pOptions));
			_identifier = ReadingIdentifier::Ptr(new ObisIdentifier());
			break;
#ifdef SML_SUPPORT
		case  meter_protocol_sml:
			_protocol = vz::protocol::Protocol::Ptr(new MeterSML(pOptions));
			_identifier = ReadingIdentifier::Ptr(new ObisIdentifier());
			break;
#endif
		case meter_protocol_fluksov2:
			_protocol = vz::protocol::Protocol::Ptr(new MeterFluksoV2(pOptions));
			_identifier = ReadingIdentifier::Ptr(new ChannelIdentifier());
			break;
#ifdef OCR_SUPPORT
		case meter_protocol_ocr:
			_protocol = vz::protocol::Protocol::Ptr(new MeterOCR(pOptions));
			_identifier = ReadingIdentifier::Ptr(new StringIdentifier());
			break;
#endif
	case meter_protocol_w1therm:
			_protocol = vz::protocol::Protocol::Ptr(new MeterW1therm(pOptions));
			_identifier = ReadingIdentifier::Ptr(new StringIdentifier());
			break;
#ifdef OMS_SUPPORT
	case meter_protocol_oms:
		_protocol = vz::protocol::Protocol::Ptr(new MeterOMS(pOptions));
		_identifier = ReadingIdentifier::Ptr(new ObisIdentifier());
		break;
#endif
		default:
			break;
	}

	try {
		// enable
		_enable = optlist.lookup_bool(pOptions, "enabled");
	} catch (vz::OptionNotFoundException &e) {
		_enable = false; /* bye default meter is disabled */
	} catch (vz::VZException &e) {
		print(log_error, "Invalid type for enable", name());
		throw;
	}

	try {
		// skip
		_skip = optlist.lookup_bool(pOptions, "allowskip");
	} catch (vz::OptionNotFoundException &e) {
		_skip = false; /* by default meter will throw an exception if opening fails */
	} catch (vz::VZException &e) {
		print(log_error, "Invalid type for allowskip", name());
		throw;
	}

	print(log_debug, "Meter configured, %s.", name(), _enable ? "enabled" : "disabled");
}
Ejemplo n.º 2
0
void * reading_thread(void *arg) {
	std::vector<Reading> rds;
	MeterMap *mapping = static_cast<MeterMap *>(arg);
	Meter::Ptr  mtr = mapping->meter();
	time_t aggIntEnd;
	const meter_details_t *details;
	size_t n = 0;

	details = meter_get_details(mtr->protocolId());

	/* allocate memory for readings */
	for (size_t i=0; i< details->max_readings; i++) {
		Reading rd(mtr->identifier());
		rds.push_back(rd);
	}

	//pthread_cleanup_push(&reading_thread_cleanup, rds);

	print(log_debug, "Number of readers: %d", mtr->name(), details->max_readings);
	print(log_debug, "Config.daemon: %d", mtr->name(), options.daemon());
	print(log_debug, "Config.local: %d", mtr->name(), options.local());


	try {
		aggIntEnd = time(NULL);
		do { /* start thread main loop */
			aggIntEnd += mtr->aggtime(); /* end of this aggregation period */
			do { /* aggregate loop */
				/* fetch readings from meter and calculate delta */
				n = mtr->read(rds, details->max_readings);

				/* dumping meter output */
				if (options.verbosity() > log_debug) {
					print(log_debug, "Got %i new readings from meter:", mtr->name(), n);

					char identifier[MAX_IDENTIFIER_LEN];
					for (size_t i = 0; i < n; i++) {
						rds[i].unparse(/*mtr->protocolId(),*/ identifier, MAX_IDENTIFIER_LEN);
						print(log_debug, "Reading: id=%s/%s value=%.2f ts=%.3f", mtr->name(),
								identifier, rds[i].identifier()->toString().c_str(),
								rds[i].value(), rds[i].tvtod());
					}
				}

				/* update buffer length with current interval */
//				if (details->periodic == FALSE && delta > 0 && delta != mtr->interval()) {
//					print(log_debug, "Updating interval to %i", mtr->name(), delta);
//					mtr->interval(delta);
//				}

				/* insert readings into channel queues */
				for (MeterMap::iterator ch = mapping->begin(); ch!=mapping->end(); ch++) {
					Reading *add = NULL;

					//print(log_debug, "Check channel %s, n=%d", mtr->name(), ch->name(), n);

					for (size_t i = 0; i < n; i++) {
						if (*rds[i].identifier().get() == *(*ch)->identifier().get()) {
							//print(log_debug, "found channel", mtr->name());
							if ((*ch)->tvtod() < rds[i].tvtod()) {
								(*ch)->last(&rds[i]);
							}

							print(log_info, "Adding reading to queue (value=%.2f ts=%.3f)", (*ch)->name(),
									rds[i].value(), rds[i].tvtod());
							(*ch)->push(rds[i]);

							if (add == NULL) {
								add = &rds[i]; /* remember first reading which has been added to the buffer */
							}
						}
					}

					/* update buffer length */
					if (options.local()) {
						(*ch)->buffer()->keep((mtr->interval() > 0) ? ceil(options.buffer_length() / mtr->interval()) : 0);
					}
				} // channel loop
			} while((mtr->aggtime() > 0) && (time(NULL) < aggIntEnd)); /* default aggtime is -1 */

			for (MeterMap::iterator ch = mapping->begin(); ch!=mapping->end(); ch++) {

				/* aggregate buffer values if aggmode != NONE */
				(*ch)->buffer()->aggregate(mtr->aggtime(), mtr->aggFixedInterval());
				/* mark buffer "ready" */
				(*ch)->buffer()->have_newValues();

				/* shrink buffer */
				(*ch)->buffer()->clean();

				/* notify webserver and logging thread */
				(*ch)->notify();

				/* debugging */
				if (options.verbosity() >= log_debug) {
					size_t dump_len = 24;
					char *dump = (char*)malloc(dump_len);

					if (dump == NULL) {
						print(log_error, "cannot allocate buffer", (*ch)->name());
					}

					while (dump == NULL || (*ch)->dump(dump, dump_len) == NULL) {
						dump_len *= 1.5;
						free(dump);
						dump = (char*)malloc(dump_len);
					}

					print(log_debug, "Buffer dump (size=%i keep=%i): %s", (*ch)->name(),
							(*ch)->size(), (*ch)->keep(), dump);

					free(dump);
				}
			}

			if (mtr->interval() > 0) {
				print(log_info, "Next reading in %i seconds", mtr->name(), mtr->interval());
				sleep(mtr->interval());
			}
		} while (options.daemon() || options.local() || options.logging() );
	} catch (std::exception &e) {
		std::stringstream oss;
		oss << e.what();
		print(log_error, "Reading-THREAD - reading Got an exception : %s", mtr->name(), e.what());
		pthread_exit(0);
	}

	print(log_debug, "Stop reading.! ", mtr->name());
	//pthread_cleanup_pop(1);

	pthread_exit(0);
	return NULL;
}