JavaLikeCalc.JavaScript
//Same request to the device
function req(PDU) {
	reqCntr++;
	// For placing into the module ModBus
	if(!transport.length)	return this.cntr().messIO(PDU);

	// For other logical level
	reqO = SYS.XMLNode("RTU").setAttr("id","AutoPILOT").setAttr("node",addr).setText(PDU);
	if((rez=tr.messIO(reqO,"ModBus")).length)	return "10:"+rez;
	PDU = reqO.text();

	return reqO.attr("err");
}

function valSet(attr, data, dOff, dscr) {
	dOff += 4;
	vtp = "";
	val = EVAL;
	if((vlTp=data.charCodeAt(dOff)) == 4) {
		vtp = "string";
		endStr = data.indexOf("\x00", dOff+1);
		if(endStr < 0) return "12:ASCII string have no end symbol";
		val = data.slice(dOff+1, endStr);
		dOff = endStr+1;
	}
	else if(vlTp == 5) {
		vtp = "real,ro";
		val = Special.FLibSYS.floatMergeWord(data.charCodeAt(dOff+3,"UTF-16BE"), data.charCodeAt(dOff+1,"UTF-16BE"));
		dOff += 5;
	}
	else if(vlTp == 6) {
		vtp = "boolean,ro";
		val = data.charCodeAt(dOff+1);
		dOff += 2;
	}
	else if(vlTp == 7) {
		vtp = "int,ro";
		val = data.charCodeAt(dOff+1);
		dOff += 2;
	}
	else if(vlTp == 8) {
		vtp = "int,ro";
		val = data.charCodeAt(dOff+1, "UTF-16BE");
		if(val > 32767) val -= 65536;
		dOff += 3;
	} else return "11:Unknown value type "+vlTp;

	if(dscr.length && vtp.length) this.attrAdd(attr, dscr, vtp);
	this[attr].set(val, 0, 0, true);

	return "0";
}

//Seting value to the archive
function archSet(attr, vTm, vl, arh) {
	SYS.messDebug("/Pilot/"+this.cfg("SHIFR"), "attr="+attr+"; vTm="+SYS.strftime(vTm)+"; arh="+arh+"; vl="+vl);
	atrO = this[attr];
	if(!atrO || atrO.isEVal()) return;
	arguments[attr] = vl;	//Set the current-last value
	//if(vTm > atrO.time())	atrO.set(vl,vTm,0,true);
	if(atrO.arch())	atrO.arch().setVal(vTm*1e6, vl, arh);
}

//Main process
if(f_start) {
	transport_ = transport;
	rdTblsSet_ = "";
	reqCntr = 0;
	tr = EVAL;
	reset = false;
	lstATmH = lstATmD = lstATmALRM = lstATmAUDIT = 0;
	maxAItmsH = 2000, maxAItmsD = 200, maxAItmsALRM = maxAItmsAUDIT = 250;
	cTm = 0;
	iReadTable = 0;
	rdTmALRM = rdTmAUDIT = 0;
}

//Items set changing process
if(f_start || rdTblsSet != rdTblsSet_) {
	rdTblsSet_ = rdTblsSet;

	tables = new Array();

	for(off = 0; (iIt=rdTblsSet.parse(0,"\n",off)).length; ) {
		itW = new Object();
		itW.nm = iIt.parse(0, ":");
		itW.pgN = iIt.parse(1, ":").toInt();
		itW.updPer = iIt.parse(2, ":").toInt();
		itW.subReq = SYS.strEncode(iIt.parse(3,":"),"Bin");
		itW.toRead = true;
		itW.first = true;
		if(itW.nm == "128")
			itW.names = new Array("<Zero>", "Gas Quality Data Descriptor Text", "Gas Quality Data ID", "BTU Content", "Specific Gravity", "Methane Content",
				"Nitrogen Content",	"Carbon Dioxide Content", "Ethane Content", "Propane Content", "Water Content",
				"Hydrogen Sulfide Content",	"Hydrogen Content", "Carbon Monoxide Content", "Oxygen Content", "I-Butane Content",
				"N-Butane Content", "I-Pentane Content", "N-Pentane Content", "C6+ Content", "N-Hexane Content",
				"N-Heptane Content", "N-Octane Content", "N-Nonane Content", "N-Decane Content", "Helium Content",
				"Argon Content", "Air Content", "Neo-Pentane", "Audit Register Offset");
		if(itW.nm.length && itW.pgN > 0 && itW.subReq.length)	tables.push(itW);
	}
}

if(reset) {
	reset = false, cTm = 0, arhLastH = arhLastD = arhLastALRM = arhLastAUDIT = lstATmALRM = lstATmAUDIT = 0;
	for(iIt = 0; iIt < tables.length; iIt++) tables[iIt].toRead = true;
}
if(f_start || f_stop) return;

tErr = "";
prcSt = "";

//Check for the transport change and connect
if(tr.isEVal() || transport != transport_)	{
	if(!transport.length) {
		if(this.cntr().cfg("PROT") != "RTU") {
			tr = EVAL;
			tErr = "1:"+tr("Output transport is empty and the controller object is not ModBus RTU.");
		} else tr = new Object();
	}
	else tr = SYS.Transport[transport.parse(0)]["out_"+transport.parse(1)];
	transport_ = transport;
}
if(tErr.toInt()) ;
else if(tr.isEVal())
	tErr = "1:"+tr("Output transport '%1' error.").replace("%1",transport);
else if(addr < 0 || addr > 255)
	tErr = "2:"+tr("Address '%1' out of range [0...255].").replace("%1",addr.toString());
else {
	tmCur = SYS.time();

	if(reqCntr < 0) {
		if(tmCur > abs(reqCntr))	reqCntr = 0;
		else tErr = "10:"+tr("No connection, next try after %1 seconds").replace("%1",(abs(reqCntr)-tmCur).toString());
	}

	//Unified requesting for table data by the function 0x4A
	if(!tErr.toInt()) {
		if(iReadTable < tables.length) {
			itW = tables[iReadTable];
			if(itW.toRead) {
				for(page = 0; page < itW.pgN; page++) {
					data = SYS.strFromCharCode(0x4A, 5, page) + itW.subReq;
					if(tErr.toInt() || (tErr=req(data)).toInt())	break;
					if(data.charCodeAt(0) != 0x4A || data.charCodeAt(1)+2 != data.length)
						tErr = "10:"+tr("Error function %1 response.").replace("%1","0x4A");
					else
						for(dOff = 3; !tErr.toInt() && dOff < data.length; ) {
							qlt = data.charCodeAt(dOff+2);
							pId = data.charCodeAt(dOff+3);
							tErr = valSet("tbl"+itW.nm+"_"+pId, data, dOff, (itW.first?(itW.names.isEVal()?"Table "+itW.nm+" Item "+pId:itW.names[pId]):""));
						}
				}
				if(page >= itW.pgN)	{
					itW.first = false; itW.toRead = false; itW.rdTm = SYS.time();

					SYS.messDebug("/Pilot/"+this.cfg("SHIFR"), "Successfully readed table "+itW.nm);
				}
			} else { itW.toRead = (itW.updPer > 0 && (SYS.time()-itW.rdTm) > itW.updPer); }
		}
		if((iReadTable++) >= tables.length) iReadTable = 0;
	}

	//Requesting the hourly archive
	isCurTrace = (arhLastH >= maxAItmsH && (SYS.time()-lstATmH)/3600 >= 2);
	if(isCurTrace)	SYS.messDebug("/Pilot/"+this.cfg("SHIFR"), "difH="+((SYS.time()-lstATmH)/3600));
	if(arhH.length && (arhLastH < maxAItmsH || isCurTrace)) {
		// Requesting size
		if(!tErr.toInt()) {
			if(isCurTrace)	arhLastH = maxAItmsH - floor((SYS.time()-lstATmH)/3600);
			aSize = 0, itSize = 10*4;
			aOff = 4 + arhLastH*itSize;
			data = SYS.strFromCharCode(0x48, 2, 0xFF, 0xFF, 0xFF, 0);	//Requesting the records count
			if(!(tErr=req(data)).toInt())	aSize = data.charCodeAt(5,"UTF-32BE")&0xFFFFFF;
		}
		// Requesting the data
		if(!tErr.toInt() && (aSize-aOff) >= itSize) {
			data = SYS.strFromCharCode(0x48, 2, (aOff>>16)&0xFF, (aOff>>8)&0xFF, aOff&0xFF, 0xF0);
			if(!(tErr=req(data)).toInt()) {
				mbSz = data.charCodeAt(5);
				for(aOff = 6; (aOff+itSize-6) <= mbSz; aOff += itSize, arhLastH++) {
					lstATmH = data.charCodeAt(aOff,"UTF-32BE") - tmZone*3600;
					SYS.messDebug("/Pilot/"+this.cfg("SHIFR"), "lstATmH="+SYS.strftime(lstATmH));
					archSet("vAcc", lstATmH, Special.FLibSYS.floatMergeWord(data.charCodeAt(aOff+10,"UTF-16BE"), data.charCodeAt(aOff+8,"UTF-16BE")), arhH);
					archSet("dp", lstATmH, Special.FLibSYS.floatMergeWord(data.charCodeAt(aOff+14,"UTF-16BE"), data.charCodeAt(aOff+12,"UTF-16BE")), arhH);
					archSet("p", lstATmH, Special.FLibSYS.floatMergeWord(data.charCodeAt(aOff+18,"UTF-16BE"), data.charCodeAt(aOff+16,"UTF-16BE")), arhH);
					archSet("t", lstATmH, Special.FLibSYS.floatMergeWord(data.charCodeAt(aOff+22,"UTF-16BE"), data.charCodeAt(aOff+20,"UTF-16BE")), arhH);
					archSet("flowTm", lstATmH, Special.FLibSYS.floatMergeWord(data.charCodeAt(aOff+26,"UTF-16BE"), data.charCodeAt(aOff+24,"UTF-16BE")), arhH);
					archSet("grav", lstATmH, Special.FLibSYS.floatMergeWord(data.charCodeAt(aOff+30,"UTF-16BE"), data.charCodeAt(aOff+28,"UTF-16BE")), arhH);
					archSet("C", lstATmH, Special.FLibSYS.floatMergeWord(data.charCodeAt(aOff+34,"UTF-16BE"), data.charCodeAt(aOff+32,"UTF-16BE")), arhH);
					archSet("N", lstATmH, Special.FLibSYS.floatMergeWord(data.charCodeAt(aOff+38,"UTF-16BE"), data.charCodeAt(aOff+36,"UTF-16BE")), arhH);
				}
			}
		}
		prcSt += tr("Hourly archive read item %1 from %2; ").replace("%1",arhLastH.toString()).replace("%2",floor((aSize-4)/itSize).toString());
	}

	//Requesting the daily archive
	isCurTrace = (arhLastD >= maxAItmsD && (SYS.time()-lstATmD)/86400 >= 2);
	if(isCurTrace)	SYS.messDebug("/Pilot/"+this.cfg("SHIFR"), "difD="+((SYS.time()-lstATmD)/86400));
	if(arhD.length && (arhLastD < maxAItmsD || isCurTrace)) {
		// Requesting size
		if(!tErr.toInt()) {
			if(isCurTrace)	arhLastD = maxAItmsD - floor((SYS.time()-lstATmD)/86400);
			aSize = 0, itSize = 10*4;
			aOff = 4 + arhLastD*itSize;
			data = SYS.strFromCharCode(0x48, 1, 0xFF, 0xFF, 0xFF, 0);	//Requesting the records count
			if(!(tErr=req(data)).toInt())	aSize = data.charCodeAt(5,"UTF-32BE")&0xFFFFFF;
		}
		// Requesting the data
		if(!tErr.toInt() && (aSize-aOff) >= itSize) {
			data = SYS.strFromCharCode(0x48, 1, (aOff>>16)&0xFF, (aOff>>8)&0xFF, aOff&0xFF, 0xF0);
			if(!(tErr=req(data)).toInt()) {
				mbSz = data.charCodeAt(5);
				for(aOff = 6; (aOff+itSize-6) <= mbSz; aOff += itSize, arhLastD++) {
					lstATmD = data.charCodeAt(aOff,"UTF-32BE");
					SYS.messDebug("/Pilot/"+this.cfg("SHIFR"), "lstATmD="+SYS.strftime(lstATmD));
					archSet("vAcc", lstATmD, Special.FLibSYS.floatMergeWord(data.charCodeAt(aOff+10,"UTF-16BE"), data.charCodeAt(aOff+8,"UTF-16BE")), arhD);
					archSet("dp", lstATmD, Special.FLibSYS.floatMergeWord(data.charCodeAt(aOff+14,"UTF-16BE"), data.charCodeAt(aOff+12,"UTF-16BE")), arhD);
					archSet("p", lstATmD, Special.FLibSYS.floatMergeWord(data.charCodeAt(aOff+18,"UTF-16BE"), data.charCodeAt(aOff+16,"UTF-16BE")), arhD);
					archSet("t", lstATmD, Special.FLibSYS.floatMergeWord(data.charCodeAt(aOff+22,"UTF-16BE"), data.charCodeAt(aOff+20,"UTF-16BE")), arhD);
					archSet("flowTm", lstATmD, Special.FLibSYS.floatMergeWord(data.charCodeAt(aOff+26,"UTF-16BE"), data.charCodeAt(aOff+24,"UTF-16BE")), arhD);
					archSet("grav", lstATmD, Special.FLibSYS.floatMergeWord(data.charCodeAt(aOff+30,"UTF-16BE"), data.charCodeAt(aOff+28,"UTF-16BE")), arhD);
					archSet("C", lstATmD, Special.FLibSYS.floatMergeWord(data.charCodeAt(aOff+34,"UTF-16BE"), data.charCodeAt(aOff+32,"UTF-16BE")), arhD);
					archSet("N", lstATmD, Special.FLibSYS.floatMergeWord(data.charCodeAt(aOff+38,"UTF-16BE"), data.charCodeAt(aOff+36,"UTF-16BE")), arhD);
				}
			}
		}
		prcSt += tr("Daily archive read item %1 from %2; ").replace("%1",arhLastD.toString()).replace("%2",floor((aSize-4)/itSize).toString());
	}

	//Requesting the ALARMS archive
	if(arhALRM.length &&
		(arhLastALRM < maxAItmsALRM || (tmPoolEv >= 0 && (SYS.time()-rdTmALRM) > tmPoolEv)))
	{
		if(arhLastALRM >= maxAItmsALRM)	arhLastALRM = 0;
		// Requesting size
		if(!tErr.toInt()) {
			aSize = 0, itSize = 5*4;
			aOff = 4 + arhLastALRM*itSize;
			data = SYS.strFromCharCode(0x48, 0x85, 0xFF, 0xFF, 0xFF, 0);	//Requesting the records count
			if(!(tErr=req(data)).toInt())	aSize = data.charCodeAt(5,"UTF-32BE")&0xFFFFFF;
		}
		// Requesting the data
		if(!tErr.toInt() && (aSize-aOff) >= itSize) {
			data = SYS.strFromCharCode(0x48, 0x85, (aOff>>16)&0xFF, (aOff>>8)&0xFF, aOff&0xFF, 0xF0);
			if(!(tErr=req(data)).toInt()) {
				mbSz = data.charCodeAt(5);
				for(aOff = 6; (aOff+itSize-6) <= mbSz; aOff += itSize, arhLastALRM++) {
					if((lstATmALRM_=data.charCodeAt(aOff+4,"UTF-32BE")) < lstATmALRM)	continue;
					alCode = data.charCodeAt(aOff, "UTF-16BE");
					alReg = data.charCodeAt(aOff+2, "UTF-16BE");
					lstATmALRM = lstATmALRM_;
					alPrev = Special.FLibSYS.floatMergeWord(data.charCodeAt(aOff+10,"UTF-16BE"), data.charCodeAt(aOff+8,"UTF-16BE"));
					alCur = Special.FLibSYS.floatMergeWord(data.charCodeAt(aOff+14,"UTF-16BE"), data.charCodeAt(aOff+12,"UTF-16BE"));
					alUnkn = data.charCodeAt(aOff+16, "UTF-16BE");
					SYS.Archive.messPut(lstATmALRM, 0, "alPilot:"+this.cntr().cfg("ID")+"."+this.cfg("SHIFR")+"."+alReg, 4, "Pilot register "+alReg+ ": ALARM "+alPrev+" > "+alCur+" (Unknown=0x"+alUnkn.toString(16)+"): "+alCode, arhALRM);
					SYS.messDebug("/Pilot/"+this.cfg("SHIFR"), "lstATmALRM="+SYS.strftime(lstATmALRM));
				}
			}
		}
		prcSt += tr("ALARM archive read item %1 from %2; ").replace("%1",arhLastALRM.toString()).replace("%2",floor((aSize-4)/itSize).toString());
		if(arhLastALRM >= maxAItmsALRM)	rdTmALRM = SYS.time();
	}

	//Requesting the AUDITS archive
	if(arhAUDIT.length &&
		(arhLastAUDIT < maxAItmsAUDIT || (tmPoolEv >= 0 && (SYS.time()-rdTmAUDIT) > tmPoolEv)))
	{
		if(arhLastAUDIT >= maxAItmsAUDIT)	arhLastAUDIT = 0;
		// Requesting size
		if(!tErr.toInt()) {
			aSize = 0, itSize = 5*4;
			aOff = 4 + arhLastAUDIT*itSize;
			data = SYS.strFromCharCode(0x48, 0x84, 0xFF, 0xFF, 0xFF, 0);	//Requesting the records count
			if(!(tErr=req(data)).toInt())	aSize = data.charCodeAt(5,"UTF-32BE")&0xFFFFFF;
		}
		// Requesting the data
		if(!tErr.toInt() && (aSize-aOff) >= itSize) {
			data = SYS.strFromCharCode(0x48, 0x84, (aOff>>16)&0xFF, (aOff>>8)&0xFF, aOff&0xFF, 0xF0);
			if(!(tErr=req(data)).toInt()) {
				mbSz = data.charCodeAt(5);
				for(aOff = 6; (aOff+itSize-6) <= mbSz; aOff += itSize, arhLastAUDIT++) {
					if((lstATmAUDIT_=data.charCodeAt(aOff+4,"UTF-32BE")) < lstATmAUDIT)	continue;
					alCode = data.charCodeAt(aOff, "UTF-16BE");
					alReg = data.charCodeAt(aOff+2, "UTF-16BE");
					lstATmAUDIT = lstATmAUDIT_;
					alPrev = Special.FLibSYS.floatMergeWord(data.charCodeAt(aOff+10,"UTF-16BE"), data.charCodeAt(aOff+8,"UTF-16BE"));
					alCur = Special.FLibSYS.floatMergeWord(data.charCodeAt(aOff+14,"UTF-16BE"), data.charCodeAt(aOff+12,"UTF-16BE"));
					alUnkn = data.charCodeAt(aOff+16, "UTF-16BE");
					SYS.Archive.messPut(lstATmAUDIT, 0, "audPilot:"+this.cntr().cfg("ID")+"."+this.cfg("SHIFR")+"."+alReg, 4, "Pilot register "+alReg+ ": AUDIT "+alPrev+" > "+alCur+" (Unknown=0x"+alUnkn.toString(16)+"): "+alCode, arhAUDIT);
					SYS.messDebug("/Pilot/"+this.cfg("SHIFR"), "lstATmAUDIT="+SYS.strftime(lstATmAUDIT));
				}
			}
		}
		prcSt += tr("AUDIT archive read item %1 from %2; ").replace("%1",arhLastAUDIT.toString()).replace("%2",floor((aSize-4)/itSize).toString());
		if(arhLastAUDIT >= maxAItmsAUDIT)	rdTmAUDIT = SYS.time();
	}
}

//Error set
if(!tErr.length)	tErr = "0:Requests="+reqCntr;
if(tErr.toInt()) {
	if(!tr.isEVal() && tr.start()) tr.start(false);
	if(f_err != tErr) {
		SYS.messDebug("/Pilot/"+this.cfg("SHIFR"), tr("Error")+": "+tErr);
		reqCntr = -(SYS.time()+tmConTry);

		/*aLs = this.nodeList("a_");
		for(iA = 0; iA < aLs.length; iA++)
			if((aPref=aLs[iA].slice(2,5)) == "tbl")
				this[aLs[iA].slice(2)].set(EVAL_INT, 0, 0, true);

		vAcc = dp = p = t = flowTm = grav = C = N = EVAL_REAL;*/
	}
}
else if(prcSt.length)	tErr += "; "+prcSt;
f_err = tErr;