void Slave::HandleWriteTimeDate(HeaderReadIterator& arHWI)
{
	if (!mIIN.GetNeedTime()) {
		LOG_BLOCK(LEV_WARNING, "Master is attempting to write time but slave is not requesting time sync");
		return;
	}

	ObjectReadIterator obj = arHWI.BeginRead();

	if (obj.Count() != 1) {
		mRspIIN.SetParameterError(true);
		return;
	}

	millis_t val = Group50Var1::Inst()->mTime.Get(*obj);
	mpTime->SetTime(val);

	mIIN.SetNeedTime(false);

	if(mpLogger->IsEnabled(LEV_EVENT)) {
		LogEntry le(LEV_EVENT, mpLogger->GetName(), LOCATION,
		            "Time synchronized with master", TIME_SYNC_UPDATED);
		le.AddValue("MILLISEC_SINCE_EPOCH", val);
		mpLogger->Log(le);
	}
}
void Slave::HandleWriteIIN(HeaderReadIterator& arHdr)
{
	for (ObjectReadIterator obj = arHdr.BeginRead(); !obj.IsEnd(); ++obj) {
		switch (obj->Index()) {
		case IINI_DEVICE_RESTART: {
				bool value = Group80Var1::Inst()->Read(*obj, obj->Start(), obj->Index());
				if (!value) {
					mIIN.SetDeviceRestart(false);
				}
				else {
					mRspIIN.SetParameterError(true);
					ERROR_BLOCK(LEV_WARNING, "", SERR_INVALID_IIN_WRITE);
				}
				break;
			}

		case IINI_NEED_TIME:
			mpTimeTimer->Cancel();
			mpTimeTimer = NULL;
			mIIN.SetNeedTime(false);
			LOG_BLOCK(LEV_INFO, "Master forced clear time needed flag");
			break;

		default:
			mRspIIN.SetParameterError(true);
			ERROR_BLOCK(LEV_WARNING, "", SERR_INVALID_IIN_WRITE);
			break;
		}
	}
}
void ResponseLoader::ReadVto(HeaderReadIterator& arIter, SizeByVariationObject* apObj)
{
	/* Get an iterator to the object data */
	ObjectReadIterator objIter = arIter.BeginRead();

	/* Copy the object data to a VtoData instance */
	VtoData data;
	data.Copy(*objIter, arIter->GetVariation());

	/* Determine the Virtual Terminal port/channel number */
	size_t index = objIter->Index();
	if(index > std::numeric_limits<boost::uint8_t>::max()) {
		LOG_BLOCK(LEV_WARNING, "Ignoring VTO index that exceeds bit width of uint8_t: " << index);
	}
	else {
		boost::uint8_t channel = static_cast<boost::uint8_t>(index);
		Transaction t(mpVtoReader);
		this->mpVtoReader->Update(data, channel);
	}
}
void Slave::HandleOperate(const APDU& arRequest, SequenceInfo aSeqInfo)
{
	if (aSeqInfo == SI_PREV && mLastRequest == arRequest) {
		return;
	}

	mResponse.Set(FC_RESPONSE);

	for (HeaderReadIterator hdr = arRequest.BeginRead(); !hdr.IsEnd(); ++hdr) {

		ObjectReadIterator i = hdr.BeginRead();

		switch (MACRO_DNP_RADIX(hdr->GetGroup(), hdr->GetVariation())) {

		case (MACRO_DNP_RADIX(12, 1)):
			this->RespondToCommands<BinaryOutput>(Group12Var1::Inst(), i, boost::bind(&Slave::Operate<BinaryOutput>, this, _1, _2, false, hdr.info(), aSeqInfo, arRequest.GetControl().SEQ));
			break;

		case (MACRO_DNP_RADIX(41, 1)):
			this->RespondToCommands<Setpoint>(Group41Var1::Inst(), i, boost::bind(&Slave::Operate<Setpoint>, this, _1, _2, false, hdr.info(), aSeqInfo, arRequest.GetControl().SEQ));
			break;

		case (MACRO_DNP_RADIX(41, 2)):
			this->RespondToCommands<Setpoint>(Group41Var2::Inst(), i, boost::bind(&Slave::Operate<Setpoint>, this, _1, _2, false, hdr.info(), aSeqInfo, arRequest.GetControl().SEQ));
			break;

		case (MACRO_DNP_RADIX(41, 3)):
			this->RespondToCommands<Setpoint>(Group41Var3::Inst(), i, boost::bind(&Slave::Operate<Setpoint>, this, _1, _2, false, hdr.info(), aSeqInfo, arRequest.GetControl().SEQ));
			break;

		case (MACRO_DNP_RADIX(41, 4)):
			this->RespondToCommands<Setpoint>(Group41Var4::Inst(), i, boost::bind(&Slave::Operate<Setpoint>, this, _1, _2, false, hdr.info(), aSeqInfo, arRequest.GetControl().SEQ));
			break;

		default:
			mRspIIN.SetFuncNotSupported(true);
			ERROR_BLOCK(LEV_WARNING, "Object/Function mismatch", SERR_OBJ_FUNC_MISMATCH);
			break;
		}
	}
}
void Slave::HandleWriteVto(HeaderReadIterator& arHdr)
{
	Transaction tr(mVtoReader);
	for (ObjectReadIterator obj = arHdr.BeginRead(); !obj.IsEnd(); ++obj) {
		size_t index = obj->Index();

		if(index > std::numeric_limits<boost::uint8_t>::max()) {
			LOG_BLOCK(LEV_WARNING, "Ignoring VTO index that exceeds bit width of uint8_t: " << index);
		}
		else {
			/*
			 * Pass the data to the vto reader
			 */
			boost::uint8_t channel = static_cast<boost::uint8_t>(index);

			VtoData vto(arHdr->GetVariation());

			Group112Var0::Inst()->Read(*obj, arHdr->GetVariation(), vto.mpData);

			mVtoReader.Update(vto, channel);
		}
	}
}
Exemple #6
0
TaskResult TimeSync::_OnFinalResponse(const APDU& arAPDU)
{
	if(mDelay < 0) {
		ptime now = mpTimeSrc->GetUTC();

		HeaderReadIterator hri = arAPDU.BeginRead();
		if(hri.Count() != 1) {
			LOG_BLOCK(LEV_WARNING, "DelayMeas response w/ unexcpected header count");
			return TR_FAIL;
		}
		
		if(!hri->GetBaseObject()->Equals(Group52Var2::Inst())) {
			LOG_BLOCK(LEV_WARNING, "DelayMeas response w/ unexpected object: " << hri->GetBaseObject()->Name());
			return TR_FAIL;
		}

		ObjectReadIterator ori = hri.BeginRead();
		if(ori.Count() != 1) {
			LOG_BLOCK(LEV_WARNING, "DelayMeas got more than 1 object in response");
			return TR_FAIL;
		}

		millis_t send_rcv_time = (now - mStart).total_milliseconds();
		millis_t rtu_turn_around = Group52Var2::Inst()->mTime.Get(*ori);

		// The later shouldn't happen, but could cause a negative delay which would
		// result in a weird time setting
		mDelay = (send_rcv_time >= rtu_turn_around) ? (send_rcv_time - rtu_turn_around)/2 : 0;

		return TR_CONTINUE;
	}
	else {

		return TR_SUCCESS;
	}	
}